diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/Input/in_midi/info.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Plugins/Input/in_midi/info.cpp')
-rw-r--r-- | Src/Plugins/Input/in_midi/info.cpp | 940 |
1 files changed, 940 insertions, 0 deletions
diff --git a/Src/Plugins/Input/in_midi/info.cpp b/Src/Plugins/Input/in_midi/info.cpp new file mode 100644 index 00000000..6881d507 --- /dev/null +++ b/Src/Plugins/Input/in_midi/info.cpp @@ -0,0 +1,940 @@ +#include "main.h" +#include "resource.h" +#include <shlwapi.h> +#include <commdlg.h> +#include <strsafe.h> +#include "../nu/AutoWide.h" +#include "../nu/AutoCharFn.h" +#include "CompressionUtility.h" + +extern In_Module mod; + +extern "C" +{ +#include "genres.h" +} +#define HAVE_BMPVIEW + +#ifdef HAVE_BMPVIEW +static LRESULT CALLBACK BmpViewProc(HWND wnd, UINT msg, WPARAM wp, LPARAM lp) +{ + switch (msg) + { + case WM_PAINT: + { + RECT r; + GetClientRect(wnd, &r); + HDC wdc = GetDC(wnd); + HDC dc = (HDC)GetWindowLongPtr(wnd, 4); + DrawEdge(wdc, &r, EDGE_SUNKEN, BF_RECT); + if (dc) BitBlt(wdc, 2, 2, r.right - 4, r.bottom - 4, dc, 0, 0, SRCCOPY); + ReleaseDC(wnd, wdc); + ValidateRect(wnd, 0); + return 0; + } + break; + case WM_USER: + { + HDC dc = CreateCompatibleDC(0); + SelectObject(dc, (HBITMAP)lp); + SetWindowLongPtr(wnd, 0, lp); + SetWindowLongPtr(wnd, 4, (LONG_PTR)dc); + //RedrawWindow(wnd,0,0,RDW_INVALIDATE); + } + return 0; + case WM_DESTROY: + { + HBITMAP bmp = (HBITMAP)GetWindowLongPtr(wnd, 0); + HDC dc = (HDC)GetWindowLongPtr(wnd, 4); + if (dc) DeleteDC(dc); + if (bmp) DeleteObject(bmp); + } + break; + } + return DefWindowProc(wnd, msg, wp, lp); +} + +void bmpview_init() +{ + static bool got_class; + if (!got_class) + { + got_class = 1; + WNDCLASS wc = + { + 0, + BmpViewProc, + 0, 8, + MIDI_callback::GetInstance(), 0, LoadCursor(0, IDC_ARROW), 0, + 0, + L"BitmapView" + }; + RegisterClassW(&wc); + } +} +#endif + +BOOL SaveFile(HWND w, MIDI_file* mf, BOOL info); +int SaveAsGZip(string filename, const void* buffer, size_t size); + +UINT align(UINT x, UINT a) +{ + a--; + return (x + a) & ~a; +} + +typedef struct +{ + UINT ctrl_id; + DWORD riff_id; + // char * name; +} +RMI_TAG; + +static void _swap_ptrs(void** a, void* b) +{ + void* _a = *a; + *a = b; + if (_a) free(_a); +} + +#define swap_ptrs(x,y) _swap_ptrs((void**)&x,(void*)(y)) + +static RMI_TAG rmi_tagz[] = +{ + {IDC_DISP, _rv('DISP')}, + {IDC_NAME, _rv('INAM')}, + {IDC_ARTIST, _rv('IART')}, + {IDC_ALBUM, _rv('IALB')}, + {IDC_TRACK, _rv('ITRK')}, + {IDC_GENRE, _rv('IGNR')}, + {IDC_COMPOSER, _rv('ICMP')}, + {IDC_COPYRIGHT, _rv('ICOP')}, + {IDC_COMMENT, _rv('ICMT')}, + {IDC_DATE, _rv('ICRD')}, + {IDC_SOFTWARE, _rv('ISFT')}, + {IDC_ENGINEER, _rv('IENG')}, + {IDC_SUBJECT, _rv('ISBJ')}, +}; + +void SetDlgItemTextSiz(HWND wnd, UINT id, char* text, UINT siz) +{ + if (!text[siz - 1]) SetDlgItemTextA(wnd, id, text); + else + { + char* foo = (char*)alloca(siz + 1); + memcpy(foo, text, siz); + foo[siz] = 0; + SetDlgItemTextA(wnd, id, foo); + } +} + +#define N_RMI_TAGZ (sizeof(rmi_tagz)/sizeof(rmi_tagz[0])) + + +static void set_rmi_dlg_title(HWND wnd, MIDI_file* mf) +{ + char t[MAX_PATH + 100] = { 0 }; + StringCbPrintfA(t, sizeof(t), WASABI_API_LNGSTRING(STRING_RMI_INFO_FMT), (const char*)mf->path); + SetWindowTextA(wnd, t); +} + +static BOOL CALLBACK rmiproc(HWND wnd, UINT msg, WPARAM wp, LPARAM lp) +{ + switch (msg) + { + case WM_INITDIALOG: +#if defined(_WIN64) + SetWindowLong(wnd, DWLP_USER, lp); +#else + SetWindowLong(wnd, DWL_USER, lp); +#endif + { + MIDI_file* mf = (MIDI_file*)lp; + set_rmi_dlg_title(wnd, mf); + if (mf->title && *mf->title) + { + SetDlgItemTextA(wnd, IDC_DISP, mf->title); + } + if (mf->rmi_data) + { + BYTE* rmi = (BYTE*)mf->rmi_data; + int p = 4; + while (p < mf->rmi_size) + { + DWORD id = *(DWORD*)(rmi + p); + UINT n; + for (n = 0; n < N_RMI_TAGZ; n++) + { + if (id == rmi_tagz[n].riff_id) + { + SetDlgItemTextSiz(wnd, rmi_tagz[n].ctrl_id, (char*)(rmi + p + 8), *(DWORD*)(rmi + p + 4)); + break; + } + } + p += 8 + align(*(DWORD*)(rmi + p + 4), 2); + } + } +#ifdef HAVE_BMPVIEW + if (mf->bmp_data) + { + void* pixels; + BITMAPINFOHEADER* foo = (BITMAPINFOHEADER*)mf->bmp_data; + HBITMAP bmp = CreateDIBSection(0, (BITMAPINFO*)foo, DIB_RGB_COLORS, &pixels, 0, 0); + if (bmp) + { + UINT clr_used = foo->biClrUsed; + if (!clr_used) clr_used = 1 << foo->biBitCount; + BYTE* ptr = (BYTE*)foo + foo->biSize + (clr_used << 2); + int max = (BYTE*)mf->bmp_data + mf->bmp_size - ptr; + BITMAP b; + GetObject(bmp, sizeof(b), &b); + int siz = b.bmWidthBytes * b.bmHeight; + if (siz < 0) siz = -siz; + if (siz > max) siz = max; + memcpy(pixels, ptr, siz); + SendDlgItemMessage(wnd, IDC_BMPVIEW, WM_USER, 0, (long)bmp); + } + } +#endif + + } + genres_read(GetDlgItem(wnd, IDC_GENRE)); + return 1; + case WM_COMMAND: + switch (wp) + { + case IDOK: + { +#if defined(_WIN64) + MIDI_file* mf = (MIDI_file*)GetWindowLong(wnd, DWLP_USER); +#else + MIDI_file* mf = (MIDI_file*)GetWindowLong(wnd, DWL_USER); +#endif + char* title = 0; + HWND w = GetDlgItem(wnd, IDC_DISP); + UINT sz = GetWindowTextLength(w); + if (sz) + { + sz++; + title = (char*)malloc(sz); + GetWindowTextA(w, title, sz); + } + swap_ptrs(mf->title, title); + BYTE* rmi_info = 0; + UINT rmi_siz = 0; + UINT n; + for (n = 0; n < N_RMI_TAGZ; n++) + { + UINT d = GetWindowTextLength(GetDlgItem(wnd, rmi_tagz[n].ctrl_id)); + if (d) rmi_siz += align(d + 1, 2) + 8; + } + if (rmi_siz) + { + rmi_siz += 4; //'INFO' + rmi_info = (BYTE*)malloc(rmi_siz); + UINT ptr = 4; + *(DWORD*)rmi_info = _rv('INFO'); + for (n = 0; n < N_RMI_TAGZ; n++) + { + w = GetDlgItem(wnd, rmi_tagz[n].ctrl_id); + if (GetWindowTextLength(w)) + { + *(DWORD*)(rmi_info + ptr) = rmi_tagz[n].riff_id; + ptr += 4; + char* foo = (char*)(rmi_info + ptr + 4); + GetWindowTextA(w, foo, rmi_siz - (ptr + 4)); + UINT s = strlen(foo) + 1; + *(DWORD*)(rmi_info + ptr) = s; + ptr += 4 + align(s, 2); + } + } + rmi_siz = ptr; + } + mf->rmi_size = rmi_siz; + swap_ptrs(mf->rmi_data, rmi_info); + + genres_write(GetDlgItem(wnd, IDC_GENRE)); + + if (SaveFile(wnd, mf, 1)) EndDialog(wnd, 0); + } + break; + case IDCANCEL: + genres_write(GetDlgItem(wnd, IDC_GENRE)); + EndDialog(wnd, 1); + break; + } + break; + } + return 0; +} + +int show_rmi_info(HWND w, MIDI_file* mf) +{ +#ifdef HAVE_BMPVIEW + bmpview_init(); +#endif + return WASABI_API_DIALOGBOXPARAM(IDD_RMI_SHIZ, w, rmiproc, (long)mf); +} + +static bool is_local(const char* url) +{ + if (!_strnicmp(url, "file://", 7) || !strnicmp(url, "partial://", 10)) return 1; + if (url[1] == ':' && url[2] == '\\') return 1; + return strstr(url, "://") ? 0 : 1; +} + +static char* fmt_names[] = { "MIDI", "RIFF MIDI", "HMP", "HMI", "XMIDI", "MUS", "CMF", "GMD", "MIDS", "GMF", "MIDI(?)" }; + +const char* find_tag(MIDI_file* mf, DWORD id, UINT* siz); + +char* getfmtstring(MIDI_file* f, char* s) +{ + const char* z = fmt_names[f->format]; + while (z && *z) *(s++) = *(z++); + if (f->format <= 1) //MID/RMI + { + char foo[32] = { 0 }; + StringCbPrintfA(foo, sizeof(foo), WASABI_API_LNGSTRING(STRING_INFO_FORMAT_FMT), f->data[4 + 4 + 1]); + z = foo; + while (z && *z) *(s++) = *(z++); + } + if (f->info.e_type) + { + *(s++) = ' '; + *(s++) = '('; + z = f->info.e_type; + while (z && *z) *(s++) = *(z++); + *(s++) = ')'; + } + *s = 0; + return s; +} + +void file2title(const char* f, string& t); + +static const char* find_tag(MIDI_file* mf, DWORD id, UINT* siz) +{ + if (!mf->rmi_data) return 0; + char* rmi = (char*)mf->rmi_data; + int ptr = 4; + while (ptr < mf->rmi_size) + { + if (*(DWORD*)(rmi + ptr) == id) + { + UINT s = *(DWORD*)(rmi + ptr + 4); + UINT s1 = 0; + ptr += 8; + while (rmi[ptr + s1] && s1 < s) s1++; + if (siz) *siz = s1; + return rmi + ptr; + } + ptr += align(*(DWORD*)(rmi + ptr + 4), 2) + 8; + } + return 0; +} + +bool KeywordMatch(const char* mainString, const char* keyword) +{ + return !_stricmp(mainString, keyword); +} + + +static const wchar_t* pExtList[] = { L"MID",L"MIDI",L"RMI",L"KAR",L"HMP",L"HMI",L"XMI",L"MSS",L"MUS",L"CMF",L"GMD",L"MIDS",L"MIZ",L"HMZ" }; +static const int pExtDescIdList[] = { 0, 0, 0, 1, 2, 2, 3, 4, 5, 6, 7, 0, 8, 9 }; +static const int pExtDescList[] = +{ + IDS_FAMILY_STRING_MIDI, + IDS_FAMILY_STRING_KARAOKE_MIDI, + IDS_FAMILY_STRING_HMI_MIDI, + IDS_FAMILY_STRING_EXTENDED_MIDI, + IDS_FAMILY_STRING_MSS_MIDI, + IDS_FAMILY_STRING_FINALE_MIDI, + IDS_FAMILY_STRING_CREATIVE_MIDI, + IDS_FAMILY_STRING_GENERAL_MIDI_DUMP, + IDS_FAMILY_STRING_COMPRESSED_MIDI, + IDS_FAMILY_STRING_COMPRESSED_HMI_MIDI +}; + +MIDI_file* wa2_open_file(const char* url); +extern "C" __declspec(dllexport) int winampGetExtendedFileInfoW(const wchar_t* fn, const char* data, wchar_t* dest, int destlen) +{ + MIDI_file* file = 0; + + if (KeywordMatch(data, "type")) + { + dest[0] = L'0'; + dest[1] = 0; + return 1; + } + if (KeywordMatch(data, "BURNABLE")) + { + dest[0] = L'0'; + dest[1] = 0; + return 1; + } + if (KeywordMatch(data, "noburnreason")) // note: this isn't supposed to be any kind of protection - just keeps the burner from misbehaving on protected tracks + { + WASABI_API_LNGSTRINGW_BUF(IDS_MIDIS_ARE_NOT_BURNABLE, dest, destlen); + return 1; + } + if (KeywordMatch(data, "family")) + { + INT index; + LPCWSTR e; + DWORD lcid; + e = PathFindExtensionW(fn); + if (L'.' != *e || 0x00 == *(++e)) return 0; + + lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); + for (index = sizeof(pExtList) / sizeof(wchar_t*) - 1; index >= 0 && CSTR_EQUAL != CompareStringW(lcid, NORM_IGNORECASE, e, -1, pExtList[index], -1); index--); + if (index >= 0 && S_OK == StringCchCopyW(dest, destlen, WASABI_API_LNGSTRINGW(pExtDescList[pExtDescIdList[index]]))) return 1; + return 0; + } + + file = wa2_open_file(AutoCharFn(fn)); + if (!file) + { + return 0; + } + const char* ret = 0; + //else if (!_stricmp(tag,"FILEPATH") || !_stricmp(tag,"PATH")) ret=file->path; + //else if (!_stricmp(tag,"DISPLAY")) ret=file->title; + //else if (!_stricmp(tag,"FIRSTTRACK")) ret=file->info.traxnames[0]; + + if (KeywordMatch(data, "LENGTH")) + { + _itow(file->GetLength(), dest, 10); + file->Free(); + return 1; + } + else if (file->rmi_data) + { + if (KeywordMatch(data, "TITLE")) ret = find_tag(file, _rv('INAM'), 0); + else if (KeywordMatch(data, "ARTIST")) ret = find_tag(file, _rv('IART'), 0); + else if (KeywordMatch(data, "COMPOSER")) ret = find_tag(file, _rv('ICMP'), 0); + else if (KeywordMatch(data, "GENRE")) ret = find_tag(file, _rv('IGNR'), 0); + else if (KeywordMatch(data, "ALBUM")) ret = find_tag(file, _rv('IALB'), 0); + else if (KeywordMatch(data, "COPYRIGHT")) ret = find_tag(file, _rv('ICOP'), 0); + else if (KeywordMatch(data, "COMMENT")) ret = find_tag(file, _rv('ICMT'), 0); + else if (KeywordMatch(data, "TRACK")) ret = find_tag(file, _rv('ITRK'), 0); + else if (KeywordMatch(data, "DATE")) ret = find_tag(file, _rv('ICRD'), 0); + else + { + file->Free(); + return 0; + } + } + else + { + file->Free(); + return 0; + } + + if (ret) + { + lstrcpynW(dest, AutoWide(ret), destlen); + + } + file->Free(); + return !!ret; +} + + +void MIDI_file::GetTitle(char* buf, int maxlen) +{ + string file_title; + file2title(path, file_title); + lstrcpynA(buf, file_title, maxlen); +} + +//int save_gzip(MIDI_file* mf, char* path); + +static void do_ext(string& s, const char* ext) +{ + const char* p = strrchr(s, '.'); + if (p) s.truncate(p - (const char*)s); + s += ext; +} + +void* build_rmi(MIDI_file* mf, UINT* siz) +{ + UINT sz = 0x14 + align(mf->size, 2); + UINT t_sz = 0; + if (mf->title) + { + t_sz = strlen(mf->title); + if (t_sz) + { + t_sz++; //add null; + sz += 12 + align(t_sz, 2); + } + } + if (mf->rmi_data) + { + sz += align(mf->rmi_size + 8, 2); + } + if (mf->bmp_data) + { + sz += align(mf->bmp_size + 12, 2); + } + + if (mf->pDLSdata) sz += align(mf->DLSsize, 2); + + BYTE* block = (BYTE*)malloc(sz); + BYTE* b_ptr = block; + *(DWORD*)b_ptr = _rv('RIFF'); + b_ptr += 4; + *(DWORD*)b_ptr = sz - 8; + b_ptr += 4; + *(DWORD*)b_ptr = _rv('RMID'); + b_ptr += 4; + *(DWORD*)b_ptr = _rv('data'); + b_ptr += 4; + *(DWORD*)b_ptr = mf->size; + b_ptr += 4; + memcpy(b_ptr, mf->data, mf->size); + b_ptr += align(mf->size, 2); + if (t_sz) + { + *(DWORD*)b_ptr = _rv('DISP'); + b_ptr += 4; + *(DWORD*)b_ptr = t_sz + 4; + b_ptr += 4; + *(DWORD*)b_ptr = 1; + b_ptr += 4; + memcpy(b_ptr, mf->title, t_sz); + b_ptr += align(t_sz, 2); + } + if (mf->rmi_data) + { + *(DWORD*)b_ptr = _rv('LIST'); + b_ptr += 4; + *(DWORD*)b_ptr = mf->rmi_size; + b_ptr += 4; + memcpy(b_ptr, mf->rmi_data, mf->rmi_size); + b_ptr += align(mf->rmi_size, 2); + } + if (mf->bmp_data) + { + *(DWORD*)b_ptr = _rv('DISP'); + b_ptr += 4; + *(DWORD*)b_ptr = mf->bmp_size + 4; + b_ptr += 4; + *(DWORD*)b_ptr = 8; + b_ptr += 4; + memcpy(b_ptr, mf->bmp_data, mf->bmp_size); + b_ptr += align(mf->bmp_size, 2); + } + if (mf->pDLSdata) + { + memcpy(b_ptr, mf->pDLSdata, mf->DLSsize); + b_ptr += align(mf->DLSsize, 2); + } + *siz = sz; + return block; +} + +BOOL SaveFile(HWND w, MIDI_file* mf, BOOL info) +{ + BOOL rmi_only = info; + string tmp; + if (is_local(mf->path) && _strnicmp(mf->path, "partial://", 10)) + { + tmp = mf->path; + if (!info) do_ext(tmp, ".mid"); + } + else + { + info = 0; + file2title(mf->path, tmp); + tmp += ".mid"; + } + if (mf->format > 1) info = 0; //not MID/RMI + + UINT fmt = 0; + BOOL do_gzip = 0; + if (!info) + { + char filter[512] = { 0 }; + OPENFILENAMEA ofn = { sizeof(ofn),0 }; + ofn.hwndOwner = w; + ofn.lpstrFile = tmp.buffer_get(MAX_PATH + 1); + ofn.nMaxFile = MAX_PATH; + ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; + ofn.lpstrDefExt = ""; + ofn.lpstrFilter = filter; + char* pf = filter, * sf = 0; + int len = 0; +#define APPEND(x) {memcpy(pf,x,len);pf+=len;} + + if (!rmi_only) + { + sf = BuildFilterString(IDS_MIDI_FILES, "MID", &len); + APPEND(sf); + + sf = BuildFilterString(IDS_COMPRESSED_MIDI_FILES, "MIZ", &len); + APPEND(sf); + } + sf = BuildFilterString(IDS_RMI_FILES, "RMI", &len); + APPEND(sf); + + sf = BuildFilterString(IDS_COMPRESSED_RMI_FILES, "MIZ", &len); + APPEND(sf); + +#undef APPEND + * pf = 0; + + if (!GetSaveFileNameA(&ofn)) return 0; + + tmp.buffer_done(); + + fmt = ofn.nFilterIndex - 1; + + do_gzip = fmt & 1; + fmt >>= 1; + + if (rmi_only) fmt = 1; + + if (do_gzip) do_ext(tmp, ".miz"); + else if (fmt == 1) do_ext(tmp, ".rmi"); + else do_ext(tmp, ".mid"); + + + } + else + { + fmt = 1; + const char* p = strrchr(tmp, '.'); + if (p && !_stricmp(p, ".miz")) do_gzip = 1; + } + + { + if (fmt > 1) fmt = 0; + + + BOOL local = 0; + const void* buf = 0; + UINT buf_size = 0; + if (fmt == 0) + { + buf = mf->data; + buf_size = mf->size; + } + else //if (fmt==1) + { + local = 1; + buf = build_rmi(mf, &buf_size); + } + int rv; + + if (do_gzip) + { + rv = SaveAsGZip(tmp, buf, buf_size); + } + else + { + HANDLE f = CreateFileA(tmp, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); + if (f != INVALID_HANDLE_VALUE) + { + DWORD bw = 0; + WriteFile(f, buf, buf_size, &bw, 0); + CloseHandle(f); + rv = 1; + } + else rv = 0; + } + if (local) free((void*)buf); + if (!_stricmp(mf->path, tmp)) + { + mf->format = fmt; + } + if (!rv) + { + char _m[320] = { 0 }; + StringCbPrintfA(_m, sizeof(_m), WASABI_API_LNGSTRING(STRING_WRITE_ERROR_FMT), (const char*)tmp); + MessageBoxA(w, _m, ERROR, MB_ICONERROR); + } + return rv; + } +} +/// <summary> +/// Compress given buffer with GZIP format and saves to given filename +/// </summary> +/// <param name="filename"></param> +/// <param name="buffer"></param> +/// <param name="size"></param> +/// <returns></returns> +int SaveAsGZip(string filename, const void* buffer, size_t size) +{ + void* data; + size_t data_len = size; + int ret = CompressionUtility::CompressAsGZip(buffer, size, &data, data_len); + + if (ret >= 0) + { + try + { + HANDLE f = CreateFileA(filename, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); + if (f != INVALID_HANDLE_VALUE) + { + DWORD bw = 0; + WriteFile(f, data, data_len, &bw, 0); + CloseHandle(f); + return 1; + } + } + catch (...) + { + DWORD i = GetLastError(); + return 0; + } + } + + return 0; +} + +#define _pr ((MIDI_file*)(lp)) + +static cfg_struct_t<RECT> cfg_infpos("infpos", -1); + +static UINT inf_x_min = 0x80000000, inf_y_min, inf_c_x, inf_c_y; +static RECT r_trax, r_text; + +static void SetWindowRect(HWND w, RECT* r) +{ + SetWindowPos(w, 0, r->left, r->top, r->right - r->left, r->bottom - r->top, SWP_NOZORDER); +} + +void cGetWindowRect(HWND w, RECT* r) +{ + RECT tr, tr1; + GetWindowRect(w, &tr); + SetWindowPos(w, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + GetWindowRect(w, &tr1); + r->left = tr.left - tr1.left; + r->right = tr.right - tr1.left; + r->top = tr.top - tr1.top; + r->bottom = tr.bottom - tr1.top; + SetWindowRect(w, r); +} + + +#define RB_NUM 3 + +static struct +{ + UINT id, dx, dy; +} +rb_dat[RB_NUM] = +{ + {IDC_SAVE, 0, 0}, + {IDOK, 0, 0}, + {IDC_RMI_CRAP, 0, 0}, +}; + +#define BOTTOM_NUM 8 + +static struct +{ + UINT id; + UINT x, dy; +} +b_dat[BOTTOM_NUM] = +{ + {IDC_STATIC1, 0, 0}, + {IDC_STATIC2, 0, 0}, + {IDC_STATIC3, 0, 0}, + {IDC_TIX, 0, 0}, + {IDC_MS, 0, 0}, + {IDC_FSIZE, 0, 0}, + {IDC_DLS, 0, 0}, + {IDC_LOOP, 0, 0} +}; + +static void OnSize(HWND wnd) +{ + RECT cl, t; + GetClientRect(wnd, &cl); + t.left = r_text.left; + t.right = r_text.right; + t.top = r_text.top; + t.bottom = cl.bottom - (inf_c_y - r_text.bottom); + SetWindowRect(GetDlgItem(wnd, IDC_COPYRIGHT), &t); + t.left = r_trax.left; + t.right = cl.right - (inf_c_x - r_trax.right); + t.top = r_trax.top; + t.bottom = cl.bottom - (inf_c_y - r_trax.bottom); + SetWindowRect(GetDlgItem(wnd, IDC_TRAX), &t); + UINT n; + for (n = 0; n < BOTTOM_NUM; n++) + { + SetWindowPos(GetDlgItem(wnd, b_dat[n].id), 0, b_dat[n].x, cl.bottom - b_dat[n].dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + } + for (n = 0; n < RB_NUM; n++) + { + SetWindowPos(GetDlgItem(wnd, rb_dat[n].id), 0, cl.right - rb_dat[n].dx, cl.bottom - rb_dat[n].dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + } +} + +BOOL WINAPI InfoProc(HWND wnd, UINT msg, WPARAM wp, LPARAM lp) +{ + switch (msg) + { + case WM_INITDIALOG: + if (inf_x_min == 0x80000000) + { + RECT r; + GetWindowRect(wnd, &r); + inf_x_min = r.right - r.left; + inf_y_min = r.bottom - r.top; + GetClientRect(wnd, &r); + inf_c_x = r.right; + inf_c_y = r.bottom; + cGetWindowRect(GetDlgItem(wnd, IDC_COPYRIGHT), &r_text); + cGetWindowRect(GetDlgItem(wnd, IDC_TRAX), &r_trax); + UINT n; + for (n = 0; n < BOTTOM_NUM; n++) + { + cGetWindowRect(GetDlgItem(wnd, b_dat[n].id), &r); + b_dat[n].x = r.left; + b_dat[n].dy = inf_c_y - r.top; + } + for (n = 0; n < RB_NUM; n++) + { + cGetWindowRect(GetDlgItem(wnd, rb_dat[n].id), &r); + rb_dat[n].dx = inf_c_x - r.left; + rb_dat[n].dy = inf_c_y - r.top; + } + } + if (cfg_infpos.get_val().left != -1) + { + int sx = GetSystemMetrics(SM_CXSCREEN), sy = GetSystemMetrics(SM_CYSCREEN); + if (cfg_infpos.get_val().right > sx) + { + cfg_infpos.get_val().left -= cfg_infpos.get_val().right - sx; + cfg_infpos.get_val().right = sx; + } + if (cfg_infpos.get_val().bottom > sy) + { + cfg_infpos.get_val().top -= cfg_infpos.get_val().bottom - sy; + cfg_infpos.get_val().bottom = sy; + } + if (cfg_infpos.get_val().left < 0) + { + cfg_infpos.get_val().right -= cfg_infpos.get_val().left; + cfg_infpos.get_val().left = 0; + } + if (cfg_infpos.get_val().top < 0) + { + cfg_infpos.get_val().bottom -= cfg_infpos.get_val().top; + cfg_infpos.get_val().top = 0; + } + SetWindowRect(wnd, &cfg_infpos.get_val()); + OnSize(wnd); + } +#if defined(_WIN64) + SetWindowLong(wnd, DWLP_USER, lp); +#else + SetWindowLong(wnd, DWL_USER, lp); +#endif + SetDlgItemTextA(wnd, IDC_COPYRIGHT, _pr->info.copyright); + SetDlgItemInt(wnd, IDC_MS, _pr->len, 0); + SetDlgItemInt(wnd, IDC_TIX, _pr->info.tix, 0); + { + char tmp[128] = { 0 }; + getfmtstring(_pr, tmp); + SetDlgItemTextA(wnd, IDC_FORMAT, tmp); + + HANDLE f = CreateFileA(_pr->path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); + if (f != INVALID_HANDLE_VALUE) + { + StringCbPrintfA(tmp, sizeof(tmp), WASABI_API_LNGSTRING(STRING_BYTES_FMT), GetFileSize(f, 0)); + CloseHandle(f); + SetDlgItemTextA(wnd, IDC_FSIZE, tmp); + } + } + { + char tmp[1024] = { 0 }; + if (_pr->info.traxnames) + { + HWND lb = GetDlgItem(wnd, IDC_TRAX); + UINT n; + for (n = 0; n < _pr->info.ntrax; n++) + { + StringCbPrintfA(tmp, sizeof(tmp), "(%u) %s", n, (const char*)(_pr->info.traxnames[n])); + SendMessageA(lb, LB_ADDSTRING, 0, (LPARAM)tmp); + } + } + + StringCbPrintfA(tmp, sizeof(tmp), WASABI_API_LNGSTRING(STRING_TRACKS_FMT), _pr->info.ntrax); + SetDlgItemTextA(wnd, IDC_NTRAX, tmp); + if (_pr->title) + { + StringCbPrintfA(tmp, sizeof(tmp), WASABI_API_LNGSTRING(STRING_MIDI_INFO_FMT1), (const char*)_pr->title, (const char*)_pr->path); + } + else + { + StringCbPrintfA(tmp, sizeof(tmp), WASABI_API_LNGSTRING(STRING_MIDI_INFO_FMT2), (const char*)_pr->path); + } + if (_pr->flags & FLAG_INCOMPLETE) StringCbCatA(tmp, sizeof(tmp), WASABI_API_LNGSTRING(STRING_INCOMPLETE)); + SetWindowTextA(wnd, tmp); + } + if (_pr->pDLSdata) EnableWindow(GetDlgItem(wnd, IDC_DLS), 1); + if (_pr->loopstart) EnableWindow(GetDlgItem(wnd, IDC_LOOP), 1); + //if (_pr->rmi_data) EnableWindow(GetDlgItem(wnd,IDC_RMI_CRAP),1); + return 1; + case WM_SIZE: + OnSize(wnd); + break; + case WM_SIZING: + if (lp) + { + RECT* r = (RECT*)lp; + if ((UINT)(r->right - r->left) < inf_x_min) + { + if (wp != WMSZ_LEFT && wp != WMSZ_TOPLEFT && wp != WMSZ_BOTTOMLEFT) + r->right = r->left + inf_x_min; + else r->left = r->right - inf_x_min; + } + if ((UINT)(r->bottom - r->top) < inf_y_min) + { + if (wp != WMSZ_TOP && wp != WMSZ_TOPLEFT && wp != WMSZ_TOPRIGHT) + r->bottom = r->top + inf_y_min; + else r->top = r->bottom - inf_y_min; + } + } + break; + case WM_COMMAND: + if (wp == IDOK || wp == IDCANCEL) + { + EndDialog(wnd, /*changed ? 0 : 1*/0); + } + else if (wp == IDC_SAVE) + { +#if defined(_WIN64) + SaveFile(wnd, (MIDI_file*)GetWindowLong(wnd, DWLP_USER), 0); +#else + SaveFile(wnd, (MIDI_file*)GetWindowLong(wnd, DWL_USER), 0); +#endif + } + else if (wp == IDC_RMI_CRAP) + { +#if defined(_WIN64) + MIDI_file* mf = (MIDI_file*)GetWindowLong(wnd, DWLP_USER); +#else + MIDI_file* mf = (MIDI_file*)GetWindowLong(wnd, DWL_USER); +#endif + show_rmi_info(wnd, mf); + } + break; + case WM_CLOSE: + EndDialog(wnd, /*changed ? 0 : 1*/0); + break; + case WM_DESTROY: + GetWindowRect(wnd, &cfg_infpos.get_val()); + break; + } + return 0; +} +#undef _pr |