mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-28 00:20:47 +01:00
Add Winamp subsong handling (disabled)
This commit is contained in:
parent
3c14d3fdb4
commit
3d90731c2c
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user