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_flac/FileInfo.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Plugins/Input/in_flac/FileInfo.cpp')
-rw-r--r-- | Src/Plugins/Input/in_flac/FileInfo.cpp | 400 |
1 files changed, 400 insertions, 0 deletions
diff --git a/Src/Plugins/Input/in_flac/FileInfo.cpp b/Src/Plugins/Input/in_flac/FileInfo.cpp new file mode 100644 index 00000000..d0684c59 --- /dev/null +++ b/Src/Plugins/Input/in_flac/FileInfo.cpp @@ -0,0 +1,400 @@ +/* +** Copyright (C) 2007-2011 Nullsoft, Inc. +** +** This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held +** liable for any damages arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, including commercial applications, and to +** alter it and redistribute it freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. +** If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +** +** 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +** +** 3. This notice may not be removed or altered from any source distribution. +** +** Author: Ben Allison benski@winamp.com +** Created: March 1, 2007 +** +*/ + +#include <FLAC/all.h> +#include "main.h" +#include "../nu/ns_wc.h" +#include <windows.h> +#include "resource.h" +#include "Metadata.h" +#include "../nu/AutoWide.h" +#include "../nu/AutoChar.h" +#include "Stopper.h" +#include <strsafe.h> +#include <commctrl.h> +#include "../Agave/Language/api_language.h" + +bool FlacTagToWinampTag(wchar_t * tag, int len) +{ +#define TAG_ALIAS(b,a) if(!_wcsicmp(L ## a, tag)) { lstrcpynW(tag, L ## b, len); return true; } + TAG_ALIAS("title", "TITLE"); + TAG_ALIAS("artist", "ARTIST"); + TAG_ALIAS("album", "ALBUM"); + TAG_ALIAS("genre", "GENRE"); + TAG_ALIAS("comment", "COMMENT"); + TAG_ALIAS("year", "DATE"); + TAG_ALIAS("track", "TRACKNUMBER"); + TAG_ALIAS("albumartist", "ALBUM ARTIST"); + TAG_ALIAS("composer", "COMPOSER"); + TAG_ALIAS("disc", "DISCNUMBER"); + TAG_ALIAS("publisher", "PUBLISHER"); + TAG_ALIAS("conductor", "CONDUCTOR"); + TAG_ALIAS("bpm", "BPM"); + return false; +#undef TAG_ALIAS +} + +bool WinampTagToFlacTag(wchar_t * tag, int len) +{ +#define TAG_ALIAS(a,b) if(!_wcsicmp(L ## a, tag)) { lstrcpynW(tag, L ## b, len); return true; } + TAG_ALIAS("title", "TITLE"); + TAG_ALIAS("artist", "ARTIST"); + TAG_ALIAS("album", "ALBUM"); + TAG_ALIAS("genre", "GENRE"); + TAG_ALIAS("comment", "COMMENT"); + TAG_ALIAS("year", "DATE"); + TAG_ALIAS("track", "TRACKNUMBER"); + TAG_ALIAS("albumartist", "ALBUM ARTIST"); + TAG_ALIAS("composer", "COMPOSER"); + TAG_ALIAS("disc", "DISCNUMBER"); + TAG_ALIAS("publisher", "PUBLISHER"); + TAG_ALIAS("conductor", "CONDUCTOR"); + TAG_ALIAS("bpm", "BPM"); + return false; +#undef TAG_ALIAS +} + +static INT_PTR CALLBACK ChildProc_Advanced(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { + static int sel=-1; + static int ismychange=0; + wchar_t key[512]={0}; + wchar_t value[32768]={0}; + + switch(msg) + { + case WM_NOTIFYFORMAT: + return NFR_UNICODE; + case WM_INITDIALOG: + { + #define ListView_InsertColumnW(hwnd, iCol, pcol) \ + (int)SNDMSG((hwnd), LVM_INSERTCOLUMNW, (WPARAM)(int)(iCol), (LPARAM)(const LV_COLUMNW *)(pcol)) + SetWindowLongPtr(hwndDlg,GWLP_USERDATA,lParam); + sel=-1; + HWND hwndlist = GetDlgItem(hwndDlg,IDC_LIST); + ListView_SetExtendedListViewStyle(hwndlist, LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP); + LVCOLUMNW lvc = {0, }; + lvc.mask = LVCF_TEXT|LVCF_WIDTH; + lvc.pszText = WASABI_API_LNGSTRINGW(IDS_NAME); + lvc.cx = 82; + ListView_InsertColumnW(hwndlist, 0, &lvc); + lvc.pszText = WASABI_API_LNGSTRINGW(IDS_VALUE); + lvc.cx = 160; + ListView_InsertColumnW(hwndlist, 1, &lvc); + + Info *info = (Info *)lParam; + int n = info->metadata.GetNumMetadataItems(); + for(int i=0; i<n; i++) { + char key_[512] = {0}; + const char* value_ = info->metadata.EnumMetadata(i,key_,512); + if(value_ && key_[0]) { + AutoWide k(key_, CP_UTF8); + AutoWide v(value_, CP_UTF8); + LVITEMW lvi={LVIF_TEXT,i,0}; + lvi.pszText = k; + SendMessage(hwndlist,LVM_INSERTITEMW,0,(LPARAM)&lvi); + lvi.iSubItem=1; + lvi.pszText = v; + SendMessage(hwndlist,LVM_SETITEMW,0,(LPARAM)&lvi); + } + } + ListView_SetColumnWidth(hwndlist,0,LVSCW_AUTOSIZE); + ListView_SetColumnWidth(hwndlist,1,LVSCW_AUTOSIZE); + + SetDlgItemTextW(hwndDlg,IDC_NAME,L""); + SetDlgItemTextW(hwndDlg,IDC_VALUE,L""); + EnableWindow(GetDlgItem(hwndDlg,IDC_NAME),FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_VALUE),FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_DEL),FALSE); + } + break; + case WM_DESTROY: + { + HWND hwndlist = GetDlgItem(hwndDlg,IDC_LIST); + ListView_DeleteAllItems(hwndlist); + while(ListView_DeleteColumn(hwndlist,0)); + Info * info = (Info*)GetWindowLongPtr(hwndDlg,GWLP_USERDATA); + delete info; + info = 0; + } + break; + case WM_USER: + if(wParam && lParam && !ismychange) + { + wchar_t * value = (wchar_t*)lParam; + wchar_t tag[100] = {0}; + lstrcpynW(tag,(wchar_t*)wParam,100); + WinampTagToFlacTag(tag,100); + Info *info = (Info *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + if(!*value) + { + info->metadata.RemoveMetadata(AutoChar(tag,CP_UTF8)); + if(!_wcsicmp(L"ALBUM ARTIST",tag)) + { + // need to remove these two, also, or else it's gonna look like delete doesn't work + // if the file was tagged using these alternate fields + info->metadata.RemoveMetadata("ALBUMARTIST"); + info->metadata.RemoveMetadata("ENSEMBLE"); + } + if(!_wcsicmp(L"PUBLISHER",tag)) + { + // need to remove this also, or else it's gonna look like delete doesn't work + // if the file was tagged using this alternate field + info->metadata.RemoveMetadata("ORGANIZATION"); + } + if(!_wcsicmp(L"DATE",tag)) + { + // need to remove this also, or else it's gonna look like delete doesn't work + // if the file was tagged using this alternate field + info->metadata.RemoveMetadata("YEAR"); + } + if(!_wcsicmp(L"TRACKNUMBER",tag)) + { + // need to remove this also, or else it's gonna look like delete doesn't work + // if the file was tagged using this alternate field + info->metadata.RemoveMetadata("TRACK"); + } + } + else + { + info->metadata.SetMetadata(AutoChar(tag,CP_UTF8),AutoChar(value,CP_UTF8)); + } + HWND hlist = GetDlgItem(hwndDlg,IDC_LIST); + int n = ListView_GetItemCount(hlist); + for(int i=0; i<n; i++) + { + key[0]=0; + LVITEMW lvi={LVIF_TEXT,i,0}; + lvi.pszText=key; + lvi.cchTextMax=sizeof(key)/sizeof(*key); + SendMessage(hlist,LVM_GETITEMW,0,(LPARAM)&lvi); + if(!_wcsicmp(key,tag)) + { + lvi.iSubItem = 1; + lvi.pszText = value; + SendMessage(hlist,LVM_SETITEMW,0,(LPARAM)&lvi); + if(!*value) + ListView_DeleteItem(hlist,i); + else if(ListView_GetItemState(hlist,i,LVIS_SELECTED)) + SetDlgItemTextW(hwndDlg,IDC_VALUE,value); + return 0; + } + } + // bew hew, not found + LVITEMW lvi={0,0x7FFFFFF0,0}; + n = SendMessage(hlist,LVM_INSERTITEMW,0,(LPARAM)&lvi); + lvi.mask = LVIF_TEXT; + lvi.iItem = n; + lvi.iSubItem = 0; + lvi.pszText = tag; + SendMessage(hlist,LVM_SETITEMW,0,(LPARAM)&lvi); + lvi.iSubItem = 1; + lvi.pszText = value; + SendMessage(hlist,LVM_SETITEMW,0,(LPARAM)&lvi); + } + break; + case WM_NOTIFY: + { + LPNMHDR l=(LPNMHDR)lParam; + if(l->idFrom==IDC_LIST && l->code == LVN_KEYDOWN) { + if((((LPNMLVKEYDOWN)l)->wVKey) == VK_DELETE){ + int selitem = ListView_GetNextItem(l->hwndFrom,-1,LVNI_SELECTED|LVNI_FOCUSED); + if(selitem != -1) + SendMessage(hwndDlg,WM_COMMAND,MAKEWPARAM(IDC_BUTTON_DEL,BN_CLICKED),(LPARAM)GetDlgItem(hwndDlg,IDC_BUTTON_DEL)); + } + } + else if(l->idFrom==IDC_LIST && l->code == LVN_ITEMCHANGED) { + LPNMLISTVIEW lv=(LPNMLISTVIEW)lParam; + if(lv->uNewState & LVIS_SELECTED) { + int n = lv->iItem; + LVITEMW lvi={LVIF_TEXT,lv->iItem,0}; + lvi.pszText=key; + lvi.cchTextMax=sizeof(key)/sizeof(*key); + SendMessage(l->hwndFrom,LVM_GETITEMW,0,(LPARAM)&lvi); + lvi.pszText=value; + lvi.cchTextMax=sizeof(value)/sizeof(*value); + lvi.iSubItem=1; + SendMessage(l->hwndFrom,LVM_GETITEMW,0,(LPARAM)&lvi); + SetDlgItemTextW(hwndDlg,IDC_NAME,key); + SetDlgItemTextW(hwndDlg,IDC_VALUE,value); + sel = n; + EnableWindow(GetDlgItem(hwndDlg,IDC_NAME),TRUE); + EnableWindow(GetDlgItem(hwndDlg,IDC_VALUE),TRUE); + EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_DEL),TRUE); + } + if(lv->uOldState & LVIS_SELECTED) { + sel = -1; + SetDlgItemTextW(hwndDlg,IDC_NAME,L""); + SetDlgItemTextW(hwndDlg,IDC_VALUE,L""); + EnableWindow(GetDlgItem(hwndDlg,IDC_NAME),FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_VALUE),FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_DEL),FALSE); + } + } + } + break; + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDOK: + { + Info * info = (Info*)GetWindowLongPtr(hwndDlg,GWLP_USERDATA); + Stopper stopper; + if (lastfn && !_wcsicmp(lastfn, info->filename)) + stopper.Stop(); + bool success = info->metadata.Save(info->filename); + stopper.Play(); + if (success) + { + ResetMetadataCache(); + } + else + { + wchar_t title[128] = {0}; + MessageBoxW(hwndDlg,WASABI_API_LNGSTRINGW(IDS_CANNOT_SAVE_METADATA), + WASABI_API_LNGSTRINGW_BUF(IDS_ERROR_SAVING_METADATA,title,128), + MB_OK | MB_ICONWARNING); + } + } + break; + case IDC_NAME: + case IDC_VALUE: + if(HIWORD(wParam) == EN_CHANGE && sel>=0) { + LVITEMW lvi={LVIF_TEXT,sel,0}; + GetDlgItemTextW(hwndDlg,IDC_NAME,key,sizeof(key)/sizeof(*key)); + GetDlgItemTextW(hwndDlg,IDC_VALUE,value,sizeof(value)/sizeof(*value)); + lvi.pszText=key; + lvi.cchTextMax=sizeof(key)/sizeof(*key); + SendMessage(GetDlgItem(hwndDlg,IDC_LIST),LVM_SETITEMW,0,(LPARAM)&lvi); + lvi.pszText=value; + lvi.cchTextMax=sizeof(value)/sizeof(*value); + lvi.iSubItem=1; + SendMessage(GetDlgItem(hwndDlg,IDC_LIST),LVM_SETITEMW,0,(LPARAM)&lvi); + FlacTagToWinampTag(key,sizeof(key)/sizeof(*key)); + ismychange=1; + SendMessage(GetParent(hwndDlg),WM_USER,(WPARAM)key,(WPARAM)value); + ismychange=0; + } + else if(HIWORD(wParam) == EN_KILLFOCUS && sel>=0) { + GetDlgItemTextW(hwndDlg,IDC_NAME,key,sizeof(key)/sizeof(*key)); + GetDlgItemTextW(hwndDlg,IDC_VALUE,value,sizeof(value)/sizeof(*value)); + Info *info = (Info *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + char oldkeyA[100]=""; + bool newitem=true; + if(sel < info->metadata.GetNumMetadataItems()) { + info->metadata.EnumMetadata(sel,oldkeyA,100); + newitem=false; + } + AutoWide oldkey(oldkeyA); + if(!newitem && _wcsicmp(oldkey,key)) { // key changed + info->metadata.SetTag(sel,AutoChar(key,CP_UTF8)); + } else { + info->metadata.SetMetadata(AutoChar(key,CP_UTF8),AutoChar(value,CP_UTF8)); + } + FlacTagToWinampTag(key,sizeof(key)/sizeof(*key)); + ismychange=1; + SendMessage(GetParent(hwndDlg),WM_USER,(WPARAM)key,(WPARAM)value); + ismychange=0; + } + break; + case IDC_BUTTON_DEL: + if(sel >= 0){ + GetDlgItemTextW(hwndDlg,IDC_NAME,key,sizeof(key)/sizeof(*key)); + SetDlgItemTextW(hwndDlg,IDC_NAME,L""); + SetDlgItemTextW(hwndDlg,IDC_VALUE,L""); + EnableWindow(GetDlgItem(hwndDlg,IDC_NAME),FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_VALUE),FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_DEL),FALSE); + Info *info = (Info *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + if(sel < info->metadata.GetNumMetadataItems()) + info->metadata.RemoveMetadata(sel); + ListView_DeleteItem(GetDlgItem(hwndDlg,IDC_LIST),sel); + sel=-1; + FlacTagToWinampTag(key,sizeof(key)/sizeof(*key)); + ismychange=1; + SendMessage(GetParent(hwndDlg),WM_USER,(WPARAM)key,(WPARAM)L""); + ismychange=0; + } + break; + case IDC_BUTTON_DELALL: + ListView_DeleteAllItems(GetDlgItem(hwndDlg,IDC_LIST)); + SetDlgItemTextW(hwndDlg,IDC_NAME,L""); + SetDlgItemTextW(hwndDlg,IDC_VALUE,L""); + EnableWindow(GetDlgItem(hwndDlg,IDC_NAME),FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_VALUE),FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_DEL),FALSE); + sel=-1; + { + Info *info = (Info *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + int n = info->metadata.GetNumMetadataItems(); + while(n>0) { + --n; + char tag[100] = {0}; + info->metadata.EnumMetadata(n,tag,100); + MultiByteToWideCharSZ(CP_UTF8, 0, tag, -1, key, sizeof(key)/sizeof(*key)); + FlacTagToWinampTag(key,sizeof(key)/sizeof(*key)); + ismychange=1; + SendMessage(GetParent(hwndDlg),WM_USER,(WPARAM)key,(WPARAM)L""); + ismychange=0; + info->metadata.RemoveMetadata(n); + } + } + break; + case IDC_BUTTON_ADD: + { + HWND hwndlist = GetDlgItem(hwndDlg,IDC_LIST); + LVITEMW lvi={0,0x7FFFFFF0,0}; + int n = SendMessage(hwndlist,LVM_INSERTITEMW,0,(LPARAM)&lvi); + ListView_SetItemState(hwndlist,n,LVIS_SELECTED,LVIS_SELECTED); + } + break; + } + break; + } + return 0; +} + +extern "C" +{ + // return 1 if you want winamp to show it's own file info dialogue, 0 if you want to show your own (via In_Module.InfoBox) + // if returning 1, remember to implement winampGetExtendedFileInfo("formatinformation")! + __declspec(dllexport) int winampUseUnifiedFileInfoDlg(const wchar_t * fn) + { + return 1; + } + + // should return a child window of 513x271 pixels (341x164 in msvc dlg units), or return NULL for no tab. + // Fill in name (a buffer of namelen characters), this is the title of the tab (defaults to "Advanced"). + // filename will be valid for the life of your window. n is the tab number. This function will first be + // called with n == 0, then n == 1 and so on until you return NULL (so you can add as many tabs as you like). + // The window you return will recieve WM_COMMAND, IDOK/IDCANCEL messages when the user clicks OK or Cancel. + // when the user edits a field which is duplicated in another pane, do a SendMessage(GetParent(hwnd),WM_USER,(WPARAM)L"fieldname",(LPARAM)L"newvalue"); + // this will be broadcast to all panes (including yours) as a WM_USER. + __declspec(dllexport) HWND winampAddUnifiedFileInfoPane(int n, const wchar_t * filename, HWND parent, wchar_t *name, size_t namelen) + { + if(n == 0) { // add first pane + SetPropW(parent,L"INBUILT_NOWRITEINFO", (HANDLE)1); + info = new Info; + info->filename = filename; + info->metadata.Open(filename, true); + return WASABI_API_CREATEDIALOGPARAMW(IDD_INFOCHILD_ADVANCED,parent,ChildProc_Advanced,(LPARAM)info); + } + return NULL; + } +};
\ No newline at end of file |