Add Winamp subsong handling (disabled)

This commit is contained in:
bnnm 2017-08-19 10:26:21 +02:00
parent 3c14d3fdb4
commit 3d90731c2c

View File

@ -77,6 +77,7 @@ double loop_count;
int thread_priority;
int loop_forever;
int ignore_loop;
int disable_subsongs = 1;
/* plugin state */
VGMSTREAM * vgmstream = NULL;
@ -95,15 +96,29 @@ in_char lastfn[PATH_LIMIT] = {0}; /* name of the currently playing file */
/* ************************************* */
//todo safe ops
//todo there must be a better way to handle unicode...
#ifdef UNICODE_INPUT_PLUGIN
#define wa_strcpy wcscpy
#define wa_strncpy wcsncpy
#define wa_strcat wcscat
#define wa_strlen wcslen
#define wa_strchr wcschr
#define wa_sscanf swscanf
#define wa_snprintf snwprintf
#define wa_fileinfo fileinfoW
#define wa_IPC_PE_INSERTFILENAME IPC_PE_INSERTFILENAMEW
#define wa_L(x) L ##x
#else
#define wa_strcpy strcpy
#define wa_strncpy strncpy
#define wa_strcat strcat
#define wa_strlen strlen
#define wa_strchr strchr
#define wa_sscanf sscanf
#define wa_snprintf snprintf
#define wa_fileinfo fileinfo
#define wa_IPC_PE_INSERTFILENAME IPC_PE_INSERTFILENAME
#define wa_L(x) x
#endif
/* converts from utf16 to utf8 (if unicode is active) */
@ -264,7 +279,7 @@ static STREAMFILE *open_winamp_streamfile_by_wpath(const in_char *wpath) {
}
/* opens vgmstream for winamp */
static VGMSTREAM* init_vgmstream_winamp(const in_char *fn) {
static VGMSTREAM* init_vgmstream_winamp(const in_char *fn, int stream_index) {
VGMSTREAM * vgmstream = NULL;
//return init_vgmstream(fn);
@ -272,6 +287,7 @@ static VGMSTREAM* init_vgmstream_winamp(const in_char *fn) {
/* manually init streamfile to pass the stream index */
STREAMFILE *streamFile = open_winamp_streamfile_by_wpath(fn); //open_stdio_streamfile(fn);
if (streamFile) {
streamFile->stream_index = stream_index;
vgmstream = init_vgmstream_from_STREAMFILE(streamFile);
close_streamfile(streamFile);
}
@ -281,6 +297,102 @@ static VGMSTREAM* init_vgmstream_winamp(const in_char *fn) {
/* ************************************* */
/* makes a modified filename, suitable to pass parameters around */
static void make_fn_subsong(in_char * dst, int dst_size, const in_char * filename, int stream_index) {
/* Follows "(file)(config)(ext)". Winamp needs to "see" (ext) to validate, and file goes first so relative
* files work in M3Us (path is added). Protocols a la "vgmstream://(config)(file)" work but don't get full paths. */
wa_snprintf(dst,dst_size, wa_L("%s|$s=%i|.vgmstream"), filename, stream_index);
}
/* unpacks the subsongs by adding entries to the playlist */
static int split_subsongs(const in_char * filename, int stream_index, VGMSTREAM *vgmstream) {
int i, playlist_index;
HWND hPlaylistWindow;
if (disable_subsongs || vgmstream->num_streams <= 1 || (vgmstream->num_streams > 1 && stream_index > 0))
return 0; /* no split if no subsongs or playing a subsong */
hPlaylistWindow = (HWND)SendMessage(input_module.hMainWindow, WM_WA_IPC, IPC_GETWND_PE, IPC_GETWND);
playlist_index = SendMessage(input_module.hMainWindow,WM_WA_IPC,0,IPC_GETLISTPOS);
/* The only way to pass info around in Winamp is encoding it into the filename, so a fake name
* is created with the index. Then, winamp_Play (and related) intercepts and reads the index. */
for (i = 0; i < vgmstream->num_streams; i++) {
in_char stream_fn[PATH_LIMIT];
make_fn_subsong(stream_fn,PATH_LIMIT, filename, (i+1)); /* encode index in filename */
/* insert at index */
{
COPYDATASTRUCT cds = {0};
wa_fileinfo f;
wa_strncpy(f.file, stream_fn,MAX_PATH-1);
f.file[MAX_PATH-1] = '\0';
f.index = playlist_index + (i+1);
cds.dwData = wa_IPC_PE_INSERTFILENAME;
cds.lpData = (void*)&f;
cds.cbData = sizeof(wa_fileinfo);
SendMessage(hPlaylistWindow,WM_COPYDATA,0,(LPARAM)&cds);
}
/* IPC_ENQUEUEFILE can pre-set the title without needing the Playlist handle, but can't insert at index */
}
/* remove current file from the playlist */
SendMessage(hPlaylistWindow, WM_WA_IPC, IPC_PE_DELETEINDEX, playlist_index);
/* autoplay doesn't always advance to the first unpacked track, manually fails too */
//SendMessage(input_module.hMainWindow,WM_WA_IPC,playlist_index,IPC_SETPLAYLISTPOS);
//SendMessage(input_module.hMainWindow,WM_WA_IPC,0,IPC_STARTPLAY);
return 1;
}
/* parses a modified filename ('fakename') extracting tags parameters (NULL tag for first = filename) */
static int parse_fn_string(const in_char * fn, const in_char * tag, in_char * dst, int dst_size) {
in_char *end;
end = wa_strchr(fn,'|');
if (tag==NULL) {
wa_strcpy(dst,fn);
if (end)
dst[end - fn] = '\0';
return 1;
}
//todo actually find + read tags
dst[0] = '\0';
return 0;
}
static int parse_fn_int(const in_char * fn, const in_char * tag, int * num) {
in_char * start = wa_strchr(fn,'|');
//todo actually find + read tags
if (start > 0) {
wa_sscanf(start+1, wa_L("$s=%i "), num);
return 1;
} else {
*num = 0;
return 0;
}
}
/* try to detect XMPlay, which can't interact with the playlist = no splitting */
static int is_xmplay() {
if (GetModuleHandle("xmplay.exe"))
return 1;
if (GetModuleHandle("xmp-wadsp.dll"))
return 1;
if (GetModuleHandle("xmp-wma.dll"))
return 1;
return 0;
}
/* ************************************* */
/* Winamp INI reader */
static void GetINIFileName(char * iniFile) {
/* if we're running on a newer winamp version that better supports
@ -364,12 +476,34 @@ static void build_extension_list() {
}
/* unicode utils */
static void copy_title(in_char * dst, int dst_size, const in_char * src) {
in_char *p = (in_char*)src + wa_strlen(src); /* find end */
while (*p != '\\' && p >= src) /* and find last "\" */
p--;
p++;
wa_strcpy(dst,p); /* copy filename only */
static void get_title(in_char * dst, int dst_size, const in_char * fn, VGMSTREAM * infostream) {
in_char *basename;
in_char buffer[PATH_LIMIT];
in_char filename[PATH_LIMIT];
int stream_index = 0;
parse_fn_string(fn, NULL, filename,PATH_LIMIT);
parse_fn_int(fn, wa_L("$s"), &stream_index);
basename = (in_char*)filename + wa_strlen(filename); /* find end */
while (*basename != '\\' && basename >= filename) /* and find last "\" */
basename--;
basename++;
wa_strcpy(dst,basename);
/* show stream subsong number */
if (stream_index > 0) {
wa_snprintf(buffer,PATH_LIMIT, wa_L("#%i"), stream_index);
wa_strcat(dst,buffer);
}
/* show name, but not for the base stream */
if (infostream && infostream->stream_name[0] != '\0' && stream_index > 0) {
in_char stream_name[PATH_LIMIT];
wa_char_to_wchar(stream_name, PATH_LIMIT, infostream->stream_name);
wa_snprintf(buffer,PATH_LIMIT, wa_L(" (%s)"), stream_name);
wa_strcat(dst,buffer);
}
}
/* ***************************************** */
@ -433,6 +567,11 @@ void winamp_Init() {
ignore_loop = DEFAULT_IGNORE_LOOP;
}
/* XMPlay with in_vgmstream doesn't support most IPC_x messages so no playlist manipulation */
if (is_xmplay()) {
disable_subsongs = 1;
}
/* dynamically make a list of supported extensions */
build_extension_list();
}
@ -449,15 +588,28 @@ int winamp_IsOurFile(const in_char *fn) {
/* request to start playing a file */
int winamp_Play(const in_char *fn) {
int max_latency;
in_char filename[PATH_LIMIT];
int stream_index = 0;
if (vgmstream)
return 1; // TODO: this should either pop up an error box or close the file
/* check for info encoded in the filename */
parse_fn_string(fn, NULL, filename,PATH_LIMIT);
parse_fn_int(fn, wa_L("$s"), &stream_index);
/* open the stream */
vgmstream = init_vgmstream_winamp(fn);
vgmstream = init_vgmstream_winamp(filename,stream_index);
if (!vgmstream)
return 1;
/* add N subsongs to the playlist, if any */
if (split_subsongs(filename, stream_index, vgmstream)) {
close_vgmstream(vgmstream);
vgmstream = NULL;
return 1;
}
/* config */
if (ignore_loop)
vgmstream->loop_flag = 0;
@ -569,7 +721,6 @@ void winamp_SetPan(int pan) {
int winamp_InfoBox(const in_char *fn, HWND hwnd) {
char description[1024] = {0};
concatn(sizeof(description),description,PLUGIN_DESCRIPTION "\n\n");
if (!fn || !*fn) {
@ -582,8 +733,14 @@ int winamp_InfoBox(const in_char *fn, HWND hwnd) {
else {
/* some other file in playlist given by filename */
VGMSTREAM * infostream = NULL;
in_char filename[PATH_LIMIT];
int stream_index = 0;
infostream = init_vgmstream_winamp(fn);
/* check for info encoded in the filename */
parse_fn_string(fn, NULL, filename,PATH_LIMIT);
parse_fn_int(fn, wa_L("$s"), &stream_index);
infostream = init_vgmstream_winamp(filename, stream_index);
if (!infostream)
return 0;
@ -607,7 +764,7 @@ void winamp_GetFileInfo(const in_char *fn, in_char *title, int *length_in_ms) {
return;
if (title) {
copy_title(title,GETFILEINFO_TITLE_LENGTH, lastfn);
get_title(title,GETFILEINFO_TITLE_LENGTH, lastfn, vgmstream);
}
if (length_in_ms) {
@ -617,11 +774,18 @@ void winamp_GetFileInfo(const in_char *fn, in_char *title, int *length_in_ms) {
else {
/* some other file in playlist given by filename */
VGMSTREAM * infostream = NULL;
in_char filename[PATH_LIMIT];
int stream_index = 0;
infostream = init_vgmstream_winamp(fn);
/* check for info encoded in the filename */
parse_fn_string(fn, NULL, filename,PATH_LIMIT);
parse_fn_int(fn, wa_L("$s"), &stream_index);
infostream = init_vgmstream_winamp(filename, stream_index);
if (!infostream) return;
if (title) {
copy_title(title,GETFILEINFO_TITLE_LENGTH, fn);
get_title(title,GETFILEINFO_TITLE_LENGTH, fn, infostream);
}
if (length_in_ms) {