replaceVars.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #include <windows.h>
  2. #include "../../General/gen_ml/ml.h"
  3. #include "pmp.h"
  4. #include <strsafe.h>
  5. #include "api__ml_pmp.h"
  6. #include "resource1.h"
  7. extern winampMediaLibraryPlugin plugin;
  8. wchar_t * FixReplacementVars(wchar_t *str, int str_size, Device * dev, songid_t song);
  9. BOOL RecursiveCreateDirectory(wchar_t* buf1);
  10. 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);
  11. static void removebadchars(wchar_t *s) {
  12. while (s && *s)
  13. {
  14. if (*s == L'?' || *s == L'/' || *s == L'\\' || *s == L':' || *s == L'*' || *s == L'\"' || *s == L'<' || *s == L'>' || *s == L'|')
  15. *s = L'_';
  16. s = CharNextW(s);
  17. }
  18. }
  19. // Skip_Root: removes drive/host/share name in a path
  20. wchar_t * Skip_Root(wchar_t *path) {
  21. wchar_t *p = CharNext(path);
  22. wchar_t *p2 = CharNext(p);
  23. if (*path && *p == L':' && *p2 == L'\\') return CharNext(p2);
  24. else if (*path == L'\\' && *p == L'\\') {
  25. // skip host and share name
  26. int x = 2;
  27. while (x--) {
  28. while (p2 && *p2 != L'\\') {
  29. if (!p2 || !*p2) return NULL;
  30. p2 = CharNext(p2);
  31. }
  32. p2 = CharNext(p2);
  33. }
  34. return p2;
  35. }
  36. return NULL;
  37. }
  38. // RecursiveCreateDirectory: creates all non-existent folders in a path
  39. BOOL RecursiveCreateDirectory(wchar_t* buf1) {
  40. wchar_t *p=buf1;
  41. int errors = 0;
  42. if (*p) {
  43. p = Skip_Root(buf1);
  44. if (!p) return true ;
  45. wchar_t ch='c';
  46. while (ch) {
  47. while (p && *p != '\\' && *p) p=CharNext(p);
  48. ch=*p;
  49. if (p) *p=0;
  50. int pp = wcslen(buf1)-1;
  51. while(buf1[pp] == '.' ||
  52. buf1[pp] == ' ' ||
  53. (buf1[pp] == '\\' && (buf1[pp-1] == '.' || buf1[pp-1] == ' ' || buf1[pp-1] == '/'))
  54. || buf1[pp] == '/' && buf1)
  55. {
  56. if(buf1[pp] == '\\')
  57. {
  58. buf1[pp-1] = '_';
  59. pp -= 2;
  60. }else{
  61. buf1[pp] = '_';
  62. pp--;
  63. }
  64. }
  65. HANDLE h;
  66. WIN32_FIND_DATA fd;
  67. // Avoid a "There is no disk in the drive" error box on empty removable drives
  68. UINT prevErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
  69. h = FindFirstFile(buf1,&fd);
  70. SetErrorMode(prevErrorMode);
  71. if (h == INVALID_HANDLE_VALUE)
  72. {
  73. if (!CreateDirectory(buf1,NULL)) errors++;
  74. } else {
  75. FindClose(h);
  76. if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) errors++;
  77. }
  78. *p++ = ch;
  79. }
  80. }
  81. return errors != 0;
  82. }
  83. // FixReplacementVars: replaces <Artist>, <Title>, <Album>, and #, ##, ##, with appropriate data
  84. // DOES NOT add a file extention!!
  85. wchar_t * FixReplacementVars(wchar_t *str, int str_size, Device * dev, songid_t song)
  86. {
  87. wchar_t artist[256]=L"",album[256]=L"",albumartist[256]=L"",title[256]=L"",genre[256]=L"",year[10]=L"",dest[MAX_PATH]=L"";
  88. dev->getTrackArtist(song,artist,256);
  89. dev->getTrackAlbum(song,album,256);
  90. dev->getTrackAlbumArtist(song,albumartist,256);
  91. if(!albumartist[0]) lstrcpyn(albumartist,artist,256);
  92. dev->getTrackTitle(song,title,256);
  93. dev->getTrackGenre(song,genre,256);
  94. int y = dev->getTrackYear(song);
  95. if(y>0) StringCchPrintfW(year,10,L"%d",y);
  96. wchar_t unknown[32] = {0}, unknownartist[32] = {0}, unknownalbum[32] = {0};
  97. WASABI_API_LNGSTRINGW_BUF(IDS_UNKNOWN,unknown,32);
  98. WASABI_API_LNGSTRINGW_BUF(IDS_UNKNOWN_ARTIST,unknownartist,32);
  99. WASABI_API_LNGSTRINGW_BUF(IDS_UNKKNOWN_ALBUM,unknownalbum,32);
  100. doFormatFileName(dest,str,
  101. dev->getTrackTrackNum(song),
  102. *albumartist ? albumartist : unknownartist,
  103. *album ? album : unknownalbum,
  104. *title ? title : L"0",
  105. *genre ? genre : unknown,
  106. *year ? year : unknown,
  107. *artist ? artist : unknown
  108. );
  109. bool c = (str[1]==':');
  110. lstrcpyn(str,dest,str_size);
  111. if(c) str[1]=L':';
  112. return str;
  113. }
  114. static void CleanDirectory(wchar_t *str)
  115. {
  116. if (!str)
  117. return ;
  118. int l = wcslen(str);
  119. while (l--)
  120. {
  121. if (str[l] == L' '
  122. || str[l] == L'.')
  123. str[l] = 0;
  124. else
  125. break;
  126. }
  127. }
  128. 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)
  129. {
  130. CleanDirectory(artist);
  131. CleanDirectory(album);
  132. CleanDirectory(title);
  133. CleanDirectory(genre);
  134. CleanDirectory(year);
  135. while (fmt && *fmt)
  136. {
  137. int whichstr = 0;
  138. if (*fmt == L'#' && trackno != 0xdeadbeef)
  139. {
  140. int cnt = 0;
  141. while (fmt && *fmt == L'#')
  142. {
  143. fmt++;
  144. cnt++;
  145. }
  146. if (cnt > 8) cnt = 8;
  147. wchar_t specstr[32] = {0};
  148. StringCchPrintf(specstr, 32, L"%%%02dd", cnt);
  149. wchar_t tracknostr[32] = {0};
  150. StringCchPrintf(tracknostr, 32, specstr, trackno);
  151. StringCchCat(out, MAX_PATH, tracknostr);
  152. }
  153. else if (artist && !_wcsnicmp(fmt, L"<artist>", 8)) whichstr = 1;
  154. else if (album && !_wcsnicmp(fmt, L"<album>", 7)) whichstr = 2;
  155. else if (title && !_wcsnicmp(fmt, L"<title>", 7)) whichstr = 3;
  156. else if (genre && !_wcsnicmp(fmt, L"<genre>", 7)) whichstr = 4;
  157. else if (year && !_wcsnicmp(fmt, L"<year>", 6)) whichstr = 5;
  158. else if (year && !_wcsnicmp(fmt, L"<trackartist>", 13)) whichstr=6;
  159. else
  160. {
  161. wchar_t p[2] = {0};
  162. p[0] = *fmt++;
  163. if (p[0] == L'?' || p[0] == L'*' || p[0] == L'|') p[0] = L'_';
  164. else if (p[0] == L':') p[0] = L'-';
  165. else if (p[0] == L'\"') p[0] = L'\'';
  166. else if (p[0] == L'<') p[0] = L'(';
  167. else if (p[0] == L'>') p[0] = L')';
  168. p[1] = 0;
  169. StringCchCat(out, MAX_PATH, p);
  170. }
  171. if (whichstr > 0)
  172. {
  173. int islow = IsCharLowerW(fmt[1]) && IsCharLowerW(fmt[2]);
  174. int ishi = IsCharUpperW(fmt[1]) && IsCharUpperW(fmt[2]);
  175. wchar_t *src;
  176. if (whichstr == 1) { src = artist; fmt += 8; }
  177. else if (whichstr == 2) { src = album; fmt += 7; }
  178. else if (whichstr == 3) { src = title; fmt += 7; }
  179. else if (whichstr == 4) { src = genre; fmt += 7; }
  180. else if (whichstr == 5) { src = year; fmt += 6; }
  181. else if (whichstr == 6) { src= trackartist; fmt+=13; }
  182. else break;
  183. while (src && *src)
  184. {
  185. wchar_t p[2] = {src[0], 0};
  186. if (ishi) CharUpperBuffW(p, 1);
  187. else if (islow) CharLowerBuffW(p, 1);
  188. if (p[0] == L'?' || p[0] == L'*' || p[0] == L'|') p[0] = L'_';
  189. else if (p[0] == L'/' || p[0] == L'\\' || p[0] == L':') p[0] = L'-';
  190. else if (p[0] == L'\"') p[0] = L'\'';
  191. else if (p[0] == L'<') p[0] = L'(';
  192. else if (p[0] == L'>') p[0] = L')';
  193. src++;
  194. p[1] = 0;
  195. StringCchCat(out, MAX_PATH, p);
  196. }
  197. }
  198. }
  199. }