Merge pull request #498 from goutsune/xmp-dev

Improve encoding info display, now works with FFmpeg formats too. Experimental metadata parser.
This commit is contained in:
Christopher Snowhill 2019-12-05 22:51:57 -08:00 committed by GitHub
commit 8654d91d0f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -35,12 +35,14 @@ static XMPFUNC_MISC *xmpfmisc;
static XMPFUNC_FILE *xmpffile;
char working_extension_list[EXTENSION_LIST_SIZE] = {0};
char filepath[MAX_PATH];
/* plugin config */
double fade_seconds = 10.0;
double fade_delay_seconds = 10.0;
double fade_delay_seconds = 0.0;
double loop_count = 2.0;
int disable_subsongs = 1;
bool xmplay_doneloop = 0;
/* plugin state */
VGMSTREAM * vgmstream = NULL;
@ -106,6 +108,9 @@ static STREAMFILE *xmpsf_open(XMPLAY_STREAMFILE *this, const char *const filenam
newfile = xmpffile->Open(filename);
if (!newfile) return NULL;
strncpy(filepath, filename, MAX_PATH);
filepath[MAX_PATH - 1] = 0x00;
return open_xmplay_streamfile_by_xmpfile(newfile, filename, 1); /* internal XMPFILE */
}
@ -158,22 +163,212 @@ fail:
/* ************************************* */
#if 0
/* get the tags as an array of "key\0value\0", NULL-terminated */
static char *get_tags(VGMSTREAM * infostream) {
char *tags;
size_t tag_number = 20; // ?
char* tags;
int pos = 0;
tags = (char*)xmpfmisc->Alloc(tag_number+1);
tags = xmpfmisc->Alloc(1024);
memset(tags, 0x00, 1024);
for (...) {
...
}
if (infostream->stream_name != NULL && strlen(infostream->stream_name) > 0)
{
memcpy(tags + pos, "title", 5);
pos += 6;
memcpy(tags + pos, infostream->stream_name, strlen(infostream->stream_name));
pos += strlen(infostream->stream_name) + 1;
}
char* end;
char* start = NULL;
int j = 2;
for (char* i = filepath+strlen(filepath); i > filepath; i--)
{
if ((*i == '\\') && (j == 1))
{
start = i + 1;
j--;
break;
}
if ((*i == '\\') && (j == 2))
{
end = i;
j--;
}
}
tags[tag_number]=0; // terminating NULL
return tags; /* assuming XMPlay free()s this, since it Alloc()s it */
//run some sanity checks
int brace_curly = 0, brace_square = 0;
char check_ok = 0;
for (char* i = filepath; *i != 0; i++)
{
if (*i == '(')
brace_curly++;
if (*i == ')')
brace_curly--;
if (*i == '[')
brace_square++;
if (*i == ']')
brace_square--;
if (brace_curly > 1 || brace_curly < -1 || brace_square > 1 || brace_square < -1)
break;
}
if (brace_square == 0 && brace_curly == 0)
check_ok = 1;
if (start != NULL && strstr(filepath, "\\VGMPP\\") != NULL && check_ok == 1 && strchr(start, '(') != NULL)
{
char tagline[1024];
memset(tagline, 0x00, sizeof(tagline));
strncpy(tagline, start, end - start);
char* alttitle_st;
char* alttitle_ed;
char* album_st;
char* album_ed;
char* company_st;
char* company_ed;
char* company2_st;
char* company2_ed;
char* date_st;
char* date_ed;
char* platform_st;
char* platform_ed;
if (strchr(tagline, '[') != NULL) //either alternative title or platform usually
{
alttitle_st = strchr(tagline, '[') + 1;
alttitle_ed = strchr(alttitle_st, ']');
if (strchr(alttitle_st, '[') != NULL && strchr(alttitle_st, '[') > strchr(alttitle_st, '(')) //both might be present actually
{
platform_st = strchr(alttitle_st, '[') + 1;
platform_ed = strchr(alttitle_ed + 1, ']');
}
else
{
platform_st = NULL;
platform_ed = NULL;
}
}
else
{
platform_st = NULL;
platform_ed = NULL;
alttitle_st = NULL;
alttitle_ed = NULL;
}
album_st = tagline;
if (strchr(tagline, '(') < alttitle_st && alttitle_st != NULL) //square braces after curly braces -- platform
{
platform_st = alttitle_st;
platform_ed = alttitle_ed;
alttitle_st = NULL;
alttitle_ed = NULL;
album_ed = strchr(tagline, '('); //get normal title for now
}
else if (alttitle_st != NULL)
album_ed = strchr(tagline, '[');
else
album_ed = strchr(tagline, '(');
date_st = strchr(album_ed, '(') + 1; //first string in curly braces is usualy release date, I have one package with platform name there
if (date_st == NULL)
date_ed = NULL;
if (date_st[0] >= 0x30 && date_st[0] <= 0x39 && date_st[1] >= 0x30 && date_st[1] <= 0x39) //check if it contains 2 digits
{
date_ed = strchr(date_st, ')');
}
else //platform?
{
platform_st = date_st;
platform_ed = strchr(date_st, ')');
date_st = strchr(platform_ed, '(') + 1;
date_ed = strchr(date_st, ')');
}
company_st = strchr(date_ed, '(') + 1; //company name follows date
if (company_st != NULL)
{
company_ed = strchr(company_st, ')');
if (strchr(company_ed, '(') != NULL)
{
company2_st = strchr(company_ed, '(') + 1;
company2_ed = strchr(company2_st, ')');
}
else
{
company2_st = NULL;
company2_ed = NULL;
}
}
else
{
company_st = NULL;
company_ed = NULL;
company2_st = NULL;
company2_ed = NULL;
}
if (alttitle_st != NULL) //prefer alternative title, which is usually japanese
{
memcpy(tags + pos, "album", 5);
pos += 6;
memcpy(tags + pos, alttitle_st, alttitle_ed - alttitle_st);
pos += alttitle_ed - alttitle_st + 1;
}
else
{
memcpy(tags + pos, "album", 5);
pos += 6;
memcpy(tags + pos, album_st, album_ed - album_st);
pos += album_ed - album_st + 1;
}
if (date_st != NULL)
{
memcpy(tags + pos, "date", 4);
pos += 5;
memcpy(tags + pos, date_st, date_ed - date_st);
pos += date_ed - date_st + 1;
}
if (date_st != NULL)
{
memcpy(tags + pos, "genre", 5);
pos += 6;
memcpy(tags + pos, platform_st, platform_ed - platform_st);
pos += platform_ed - platform_st + 1;
}
if (company_st != NULL)
{
char combuf[256];
memset(combuf, 0x00, sizeof(combuf));
char tmp[128];
memset(tmp, 0x00, sizeof(tmp));
memcpy(tmp, company_st, company_ed - company_st);
if (company2_st != NULL)
{
char tmp2[128];
memset(tmp2, 0x00, sizeof(tmp2));
memcpy(tmp2, company2_st, company2_ed - company2_st);
sprintf(combuf, "\r\n\r\nDeveloper\t%s\r\nPublisher\t%s", tmp, tmp2);
}
else
sprintf(combuf, "\r\n\r\nDeveloper\t%s", tmp);
memcpy(tags + pos, "comment", 7);
pos += 8;
memcpy(tags + pos, combuf, strlen(combuf));
pos += strlen(combuf) + 1;
}
}
return tags; /* assuming XMPlay free()s this, since it Alloc()s it */
}
#endif
/* Adds ext to XMPlay's extension list. */
static int add_extension(int length, char * dst, const char * ext) {
@ -277,6 +472,7 @@ DWORD WINAPI xmplay_GetFileInfo(const char *filename, XMPFILE file, float **leng
if (disable_subsongs || subsong_count == 0)
subsong_count = 1;
*tags = get_tags(infostream);
close_vgmstream(infostream);
return subsong_count;
@ -324,7 +520,7 @@ void WINAPI xmplay_SetFormat(XMPFORMAT *form) {
/* get tags, return NULL to delay title update (OPTIONAL) */
char * WINAPI xmplay_GetTags() {
return NULL; //get_tags(vgmstream);
return get_tags(vgmstream);
}
/* main panel info text (short file info) */
@ -342,6 +538,18 @@ void WINAPI xmplay_GetInfoText(char* format, char* length) {
samples = vgmstream->num_samples;
bps = get_vgmstream_average_bitrate(vgmstream) / 1000;
get_vgmstream_coding_description(vgmstream, fmt, sizeof(fmt));
if (strcmp(fmt, "FFmpeg") == 0)
{
char buffer[1024];
buffer[0] = '\0';
describe_vgmstream(vgmstream, buffer, sizeof(buffer));
char* enc_tmp = strstr(buffer, "encoding: ") + 10;
char* enc_end = strstr(enc_tmp, "\n");
int len = (int)enc_end - (int)enc_tmp;
memset(fmt, 0x00, sizeof(fmt));
strncpy(fmt, enc_tmp, len);
}
t = samples / rate;
tmin = t / 60;
@ -365,9 +573,9 @@ void WINAPI xmplay_GetGeneralInfo(char* buf) {
describe_vgmstream(vgmstream,description,sizeof(description));
/* tags are divided with a tab and lines with carriage return so we'll do some guetto fixin' */
int tag_done = 0;
description[0] -= 32; //Replace small letter with capital for consistency with XMPlay's output
for (i = 0; i < 1024; i++) {
int tag_done = 0;
if (description[i] == '\0')
break;
@ -379,11 +587,13 @@ void WINAPI xmplay_GetGeneralInfo(char* buf) {
if (description[i] == '\n') {
description[i] = '\r';
if (description[i+1])
description[i+1] -= 32; //Replace small letter with capital for consistency with XMPlay's output
tag_done = 0;
}
}
sprintf(buf,"vgmstream\t\r%s\r", description);
sprintf(buf,"%s", description);
}
/* get the seeking granularity in seconds */
@ -396,6 +606,9 @@ double WINAPI xmplay_SetPosition(DWORD pos) {
double cpos = (double)framesDone / (double)vgmstream->sample_rate;
double time = pos * xmplay_GetGranularity();
if (pos == XMPIN_POS_AUTOLOOP || pos == XMPIN_POS_LOOP)
xmplay_doneloop = 1;
#if 0
/* set a subsong */
if (!disable_subsongs && (pos & XMPIN_POS_SUBSONG)) {
@ -447,6 +660,7 @@ DWORD WINAPI xmplay_Process(float* buf, DWORD bufsize) {
UINT32 i, j, todo, done;
BOOL doLoop = xmpfin->GetLooping();
float *sbuf = buf;
UINT32 samplesTodo;
@ -474,7 +688,7 @@ DWORD WINAPI xmplay_Process(float* buf, DWORD bufsize) {
sbuf = buf;
/* fade */
if (!doLoop && framesDone + done > framesLength) {
if ((!doLoop || xmplay_doneloop) && vgmstream->loop_flag && framesDone + done > framesLength) {
long fadeStart = (framesLength > framesDone) ? framesLength : framesDone;
long fadeEnd = (framesDone + done) > stream_length_samples ? stream_length_samples : (framesDone + done);
long fadePos;