2024-07-18 23:50:22 +02:00
|
|
|
#include "in_vgmstream.h"
|
|
|
|
|
|
|
|
|
|
|
|
/* Adds ext to Winamp's extension list */
|
|
|
|
static int add_extension(char* dst, int dst_len, const char* ext) {
|
|
|
|
int ext_len;
|
|
|
|
|
|
|
|
ext_len = strlen(ext);
|
|
|
|
if (dst_len <= ext_len + 1)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
strcpy(dst, ext); /* seems winamp uppercases this if needed */
|
|
|
|
dst[ext_len] = ';';
|
|
|
|
|
|
|
|
return ext_len + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Creates Winamp's extension list, a single string that ends with \0\0.
|
|
|
|
* Each extension must be in this format: "extensions\0Description\0"
|
|
|
|
*
|
|
|
|
* The list is used to accept extensions by default when IsOurFile returns 0, to register file
|
|
|
|
* types, and in the open dialog's type combo. Format actually can be:
|
|
|
|
* - "ext1;ext2;...\0EXTS Audio Files (*.ext1; *.ext2; *...\0", //single line with all
|
|
|
|
* - "ext1\0EXT1 Audio File (*.ext1)\0ext2\0EXT2 Audio File (*.ext2)\0...", //multiple lines
|
|
|
|
* Open dialog's text (including all plugin's "Description") seems limited to old MAX_PATH 260
|
|
|
|
* (max size for "extensions" checks seems ~0x40000 though). Given vgmstream's huge number
|
|
|
|
* of exts, use single line to (probably) work properly with dialogs (used to be multi line).
|
|
|
|
*/
|
|
|
|
void build_extension_list(char* winamp_list, int winamp_list_size) {
|
|
|
|
const char** ext_list;
|
|
|
|
size_t ext_list_len;
|
|
|
|
int i, written;
|
|
|
|
int description_size = 0x100; /* reserved max at the end */
|
|
|
|
|
|
|
|
winamp_list[0] = '\0';
|
|
|
|
winamp_list[1] = '\0';
|
|
|
|
|
|
|
|
ext_list = vgmstream_get_formats(&ext_list_len);
|
|
|
|
|
|
|
|
for (i = 0; i < ext_list_len; i++) {
|
|
|
|
int used = add_extension(winamp_list, winamp_list_size - description_size, ext_list[i]);
|
|
|
|
if (used <= 0) {
|
2024-08-10 23:43:41 +02:00
|
|
|
//vgm_logi("build_extension_list: not enough buf for all exts\n");
|
2024-07-18 23:50:22 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
winamp_list += used;
|
|
|
|
winamp_list_size -= used;
|
|
|
|
}
|
|
|
|
if (i > 0) {
|
|
|
|
winamp_list[-1] = '\0'; /* last "ext;" to "ext\0" */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* generic description for the info dialog since we can't really show everything */
|
|
|
|
written = snprintf(winamp_list, winamp_list_size - 2, "vgmstream Audio Files%c", '\0');
|
|
|
|
|
|
|
|
/* should end with double \0 */
|
|
|
|
if (written < 0) {
|
|
|
|
winamp_list[0] = '\0';
|
|
|
|
winamp_list[1] = '\0';
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
winamp_list[written + 0] = '\0';
|
|
|
|
winamp_list[written + 1] = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 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 subsong_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, subsong_index);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* unpacks the subsongs by adding entries to the playlist */
|
|
|
|
bool split_subsongs(const in_char* filename, int subsong_index, VGMSTREAM* vgmstream) {
|
|
|
|
int i, playlist_index;
|
|
|
|
HWND hPlaylistWindow;
|
|
|
|
|
|
|
|
|
|
|
|
if (settings.disable_subsongs || vgmstream->num_streams <= 1)
|
|
|
|
return 0; /* don't split if no subsongs */
|
|
|
|
if (subsong_index > 0 || vgmstream->stream_index > 0)
|
|
|
|
return 0; /* no split if already playing 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++) {
|
2024-08-18 17:50:55 +02:00
|
|
|
in_char stream_fn[WINAMP_PATH_LIMIT];
|
2024-07-18 23:50:22 +02:00
|
|
|
|
2024-08-18 17:50:55 +02:00
|
|
|
make_fn_subsong(stream_fn, WINAMP_PATH_LIMIT, filename, (i+1)); /* encode index in filename */
|
2024-07-18 23:50:22 +02:00
|
|
|
|
|
|
|
/* 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, but manually fails somehow */
|
|
|
|
//SendMessage(input_module.hMainWindow,WM_WA_IPC,playlist_index,IPC_SETPLAYLISTPOS);
|
|
|
|
//SendMessage(input_module.hMainWindow,WM_WA_IPC,0,IPC_STARTPLAY);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|