winamp/Src/Plugins/Library/ml_pmp/replaceVars.cpp
2024-09-24 14:54:57 +02:00

213 lines
6.1 KiB
C++

#include <windows.h>
#include "../../General/gen_ml/ml.h"
#include "pmp.h"
#include <strsafe.h>
#include "api__ml_pmp.h"
#include "resource1.h"
extern winampMediaLibraryPlugin plugin;
wchar_t * FixReplacementVars(wchar_t *str, int str_size, Device * dev, songid_t song);
BOOL RecursiveCreateDirectory(wchar_t* buf1);
void doFormatFileName(wchar_t out[MAX_PATH], wchar_t *fmt, int trackno, wchar_t *artist, wchar_t *album, wchar_t *title, wchar_t *genre, wchar_t *year, wchar_t *trackartist);
static void removebadchars(wchar_t *s) {
while (s && *s)
{
if (*s == L'?' || *s == L'/' || *s == L'\\' || *s == L':' || *s == L'*' || *s == L'\"' || *s == L'<' || *s == L'>' || *s == L'|')
*s = L'_';
s = CharNextW(s);
}
}
// Skip_Root: removes drive/host/share name in a path
wchar_t * Skip_Root(wchar_t *path) {
wchar_t *p = CharNext(path);
wchar_t *p2 = CharNext(p);
if (*path && *p == L':' && *p2 == L'\\') return CharNext(p2);
else if (*path == L'\\' && *p == L'\\') {
// skip host and share name
int x = 2;
while (x--) {
while (p2 && *p2 != L'\\') {
if (!p2 || !*p2) return NULL;
p2 = CharNext(p2);
}
p2 = CharNext(p2);
}
return p2;
}
return NULL;
}
// RecursiveCreateDirectory: creates all non-existent folders in a path
BOOL RecursiveCreateDirectory(wchar_t* buf1) {
wchar_t *p=buf1;
int errors = 0;
if (*p) {
p = Skip_Root(buf1);
if (!p) return true ;
wchar_t ch='c';
while (ch) {
while (p && *p != '\\' && *p) p=CharNext(p);
ch=*p;
if (p) *p=0;
int pp = wcslen(buf1)-1;
while(buf1[pp] == '.' ||
buf1[pp] == ' ' ||
(buf1[pp] == '\\' && (buf1[pp-1] == '.' || buf1[pp-1] == ' ' || buf1[pp-1] == '/'))
|| buf1[pp] == '/' && buf1)
{
if(buf1[pp] == '\\')
{
buf1[pp-1] = '_';
pp -= 2;
}else{
buf1[pp] = '_';
pp--;
}
}
HANDLE h;
WIN32_FIND_DATA fd;
// Avoid a "There is no disk in the drive" error box on empty removable drives
UINT prevErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
h = FindFirstFile(buf1,&fd);
SetErrorMode(prevErrorMode);
if (h == INVALID_HANDLE_VALUE)
{
if (!CreateDirectory(buf1,NULL)) errors++;
} else {
FindClose(h);
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) errors++;
}
*p++ = ch;
}
}
return errors != 0;
}
// FixReplacementVars: replaces <Artist>, <Title>, <Album>, and #, ##, ##, with appropriate data
// DOES NOT add a file extention!!
wchar_t * FixReplacementVars(wchar_t *str, int str_size, Device * dev, songid_t song)
{
wchar_t artist[256]=L"",album[256]=L"",albumartist[256]=L"",title[256]=L"",genre[256]=L"",year[10]=L"",dest[MAX_PATH]=L"";
dev->getTrackArtist(song,artist,256);
dev->getTrackAlbum(song,album,256);
dev->getTrackAlbumArtist(song,albumartist,256);
if(!albumartist[0]) lstrcpyn(albumartist,artist,256);
dev->getTrackTitle(song,title,256);
dev->getTrackGenre(song,genre,256);
int y = dev->getTrackYear(song);
if(y>0) StringCchPrintfW(year,10,L"%d",y);
wchar_t unknown[32] = {0}, unknownartist[32] = {0}, unknownalbum[32] = {0};
WASABI_API_LNGSTRINGW_BUF(IDS_UNKNOWN,unknown,32);
WASABI_API_LNGSTRINGW_BUF(IDS_UNKNOWN_ARTIST,unknownartist,32);
WASABI_API_LNGSTRINGW_BUF(IDS_UNKKNOWN_ALBUM,unknownalbum,32);
doFormatFileName(dest,str,
dev->getTrackTrackNum(song),
*albumartist ? albumartist : unknownartist,
*album ? album : unknownalbum,
*title ? title : L"0",
*genre ? genre : unknown,
*year ? year : unknown,
*artist ? artist : unknown
);
bool c = (str[1]==':');
lstrcpyn(str,dest,str_size);
if(c) str[1]=L':';
return str;
}
static void CleanDirectory(wchar_t *str)
{
if (!str)
return ;
int l = wcslen(str);
while (l--)
{
if (str[l] == L' '
|| str[l] == L'.')
str[l] = 0;
else
break;
}
}
void doFormatFileName(wchar_t out[MAX_PATH], wchar_t *fmt, int trackno, wchar_t *artist, wchar_t *album, wchar_t *title, wchar_t *genre, wchar_t *year, wchar_t *trackartist)
{
CleanDirectory(artist);
CleanDirectory(album);
CleanDirectory(title);
CleanDirectory(genre);
CleanDirectory(year);
while (fmt && *fmt)
{
int whichstr = 0;
if (*fmt == L'#' && trackno != 0xdeadbeef)
{
int cnt = 0;
while (fmt && *fmt == L'#')
{
fmt++;
cnt++;
}
if (cnt > 8) cnt = 8;
wchar_t specstr[32] = {0};
StringCchPrintf(specstr, 32, L"%%%02dd", cnt);
wchar_t tracknostr[32] = {0};
StringCchPrintf(tracknostr, 32, specstr, trackno);
StringCchCat(out, MAX_PATH, tracknostr);
}
else if (artist && !_wcsnicmp(fmt, L"<artist>", 8)) whichstr = 1;
else if (album && !_wcsnicmp(fmt, L"<album>", 7)) whichstr = 2;
else if (title && !_wcsnicmp(fmt, L"<title>", 7)) whichstr = 3;
else if (genre && !_wcsnicmp(fmt, L"<genre>", 7)) whichstr = 4;
else if (year && !_wcsnicmp(fmt, L"<year>", 6)) whichstr = 5;
else if (year && !_wcsnicmp(fmt, L"<trackartist>", 13)) whichstr=6;
else
{
wchar_t p[2] = {0};
p[0] = *fmt++;
if (p[0] == L'?' || p[0] == L'*' || p[0] == L'|') p[0] = L'_';
else if (p[0] == L':') p[0] = L'-';
else if (p[0] == L'\"') p[0] = L'\'';
else if (p[0] == L'<') p[0] = L'(';
else if (p[0] == L'>') p[0] = L')';
p[1] = 0;
StringCchCat(out, MAX_PATH, p);
}
if (whichstr > 0)
{
int islow = IsCharLowerW(fmt[1]) && IsCharLowerW(fmt[2]);
int ishi = IsCharUpperW(fmt[1]) && IsCharUpperW(fmt[2]);
wchar_t *src;
if (whichstr == 1) { src = artist; fmt += 8; }
else if (whichstr == 2) { src = album; fmt += 7; }
else if (whichstr == 3) { src = title; fmt += 7; }
else if (whichstr == 4) { src = genre; fmt += 7; }
else if (whichstr == 5) { src = year; fmt += 6; }
else if (whichstr == 6) { src= trackartist; fmt+=13; }
else break;
while (src && *src)
{
wchar_t p[2] = {src[0], 0};
if (ishi) CharUpperBuffW(p, 1);
else if (islow) CharLowerBuffW(p, 1);
if (p[0] == L'?' || p[0] == L'*' || p[0] == L'|') p[0] = L'_';
else if (p[0] == L'/' || p[0] == L'\\' || p[0] == L':') p[0] = L'-';
else if (p[0] == L'\"') p[0] = L'\'';
else if (p[0] == L'<') p[0] = L'(';
else if (p[0] == L'>') p[0] = L')';
src++;
p[1] = 0;
StringCchCat(out, MAX_PATH, p);
}
}
}
}