tagz.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. /** (c) Nullsoft, Inc. C O N F I D E N T I A L
  2. ** Filename:
  3. ** Project:
  4. ** Description:
  5. ** Author: Ben Allison [email protected]
  6. ** Created:
  7. **/
  8. #include "main.h"
  9. #include "tagz.h"
  10. #include "../tagz/ifc_tagprovider.h"
  11. #include "../tagz/ifc_tagparams.h"
  12. #include "api.h"
  13. #include "TagProvider.h"
  14. #include "../nu/AutoWide.h"
  15. #include "../nu/AutoChar.h"
  16. #include "../nu/ns_wc.h"
  17. extern "C"
  18. {
  19. typedef char * (*GetTagFunc)(const char * tag, void * p);
  20. typedef void (*FreeTagFunc)(char * tag,void * p);
  21. typedef wchar_t * (*GetTagFuncW)(const wchar_t * tag, void * p);
  22. typedef void (*FreeTagFuncW)(wchar_t * tag,void * p);
  23. }
  24. class TagParameters : public ifc_tagparams
  25. {
  26. public:
  27. TagParameters(const wchar_t *_filename) :filename(_filename){}
  28. void *GetParameter(const GUID *parameterID)
  29. {
  30. if (*parameterID == filenameParameterID)
  31. return (void *)filename;
  32. return 0;
  33. }
  34. protected:
  35. RECVS_DISPATCH;
  36. private:
  37. const wchar_t *filename;
  38. };
  39. class ExternalTagProvider : public ifc_tagprovider
  40. {
  41. public:
  42. ExternalTagProvider(GetTagFunc getter, FreeTagFunc freer, void *context);
  43. wchar_t *GetTag(const wchar_t *name, ifc_tagparams *parameters);
  44. void FreeTag(wchar_t *Tag);
  45. protected:
  46. RECVS_DISPATCH;
  47. private:
  48. GetTagFunc externalGetTag;
  49. FreeTagFunc externalFreeTag;
  50. void *externalContext;
  51. };
  52. class ExtendedTagProvider : public ifc_tagprovider
  53. {
  54. public:
  55. ExtendedTagProvider(const wchar_t *_filename, GetTagFuncW getter, FreeTagFuncW freer, void *context, bool _useExtendedInfo);
  56. wchar_t *GetTag(const wchar_t *name, ifc_tagparams *parameters);
  57. void FreeTag(char *Tag);
  58. protected:
  59. RECVS_DISPATCH;
  60. private:
  61. GetTagFuncW externalGetTag;
  62. FreeTagFuncW externalFreeTag;
  63. void *externalContext;
  64. const wchar_t *filename;
  65. bool useExtendedInfo;
  66. };
  67. static void CleanupTitle(char *title)
  68. {
  69. while (title && *title)
  70. {
  71. if (*title == '\n' || *title == '\r')
  72. *title = ' ';
  73. title = CharNextA(title);
  74. }
  75. }
  76. static void CleanupTitleW(wchar_t *title)
  77. {
  78. while (title && *title)
  79. {
  80. if (*title == L'\n' || *title == L'\r')
  81. *title = L' ';
  82. title = CharNextW(title);
  83. }
  84. }
  85. void FormatTitle(waFormatTitle *format)
  86. {
  87. AutoWide wideSpec(format->spec);
  88. wchar_t *spec = (format->spec ? wideSpec : config_titlefmt);
  89. if (format->out && format->out_len)
  90. {
  91. memset(format->out, 0, format->out_len);
  92. if (WINAMP5_API_TAGZ)
  93. {
  94. if (format->TAGFUNC)
  95. {
  96. ExternalTagProvider provider(format->TAGFUNC, format->TAGFREEFUNC, format->p);
  97. wchar_t *tempOut = (wchar_t *)calloc(format->out_len, sizeof(wchar_t));
  98. if (tempOut)
  99. {
  100. WINAMP5_API_TAGZ->format(spec, tempOut, format->out_len, &provider, 0 /*&parameters*/);
  101. WideCharToMultiByteSZ(CP_ACP, 0, tempOut, -1, format->out, format->out_len, 0, 0);
  102. free(tempOut);
  103. }
  104. }
  105. else
  106. {
  107. AutoWide wideFn((char *)format->p); // we'd better hope it's the filename!
  108. TagParameters parameters(wideFn);
  109. wchar_t *tempOut = (wchar_t *)calloc(format->out_len, sizeof(wchar_t));
  110. if (tempOut)
  111. {
  112. WINAMP5_API_TAGZ->format(spec, tempOut, format->out_len, tagProvider, &parameters);
  113. WideCharToMultiByteSZ(CP_ACP, 0, tempOut, -1, format->out, format->out_len, 0, 0);
  114. free(tempOut);
  115. }
  116. }
  117. CleanupTitle(format->out);
  118. }
  119. }
  120. }
  121. void FormatTitleExtended(waFormatTitleExtended *format)
  122. {
  123. if (!format->filename || format->filename && !*format->filename) return;
  124. const wchar_t *spec = (format->spec ? format->spec : config_titlefmt);
  125. if (format->out && format->out_len)
  126. {
  127. if (WINAMP5_API_TAGZ)
  128. {
  129. ExtendedTagProvider provider(format->filename, format->TAGFUNC, format->TAGFREEFUNC, format->p, !!format->useExtendedInfo);
  130. WINAMP5_API_TAGZ->format(spec, format->out, format->out_len, &provider, 0 /*&parameters*/);
  131. CleanupTitleW(format->out);
  132. }
  133. else
  134. {
  135. lstrcpynW(format->out, format->filename, format->out_len);
  136. PathStripPathW(format->out);
  137. }
  138. }
  139. }
  140. int FormatTitle(waHookTitleStructW *hts)
  141. {
  142. if (hts && hts->title &&
  143. ((hts->force_useformatting&1) || !(PathIsURLW(hts->filename) && StrCmpNIW(hts->filename, L"cda://", 6))))
  144. {
  145. wchar_t buf[32] = {0};
  146. wchar_t buf2[32] = {0};
  147. hts->length = -1;
  148. hts->title[0] = 0;
  149. if (in_get_extended_fileinfoW(hts->filename, L"length", buf, 32) ||
  150. in_get_extended_fileinfoW(hts->filename, L"type", buf2, 32))
  151. {
  152. hts->length = StrToIntW(buf);
  153. if (hts->length <= 0)
  154. hts->length = -1;
  155. else
  156. hts->length /= 1000;
  157. if (WINAMP5_API_TAGZ)
  158. {
  159. TagParameters parameters(hts->filename);
  160. WINAMP5_API_TAGZ->format(config_titlefmt, hts->title, 2048, tagProvider, &parameters);
  161. }
  162. CleanupTitleW(hts->title);
  163. if (hts->title[0]) return 1;
  164. }
  165. }
  166. return 0;
  167. }
  168. namespace Winamp
  169. {
  170. /* our tag getting functions */
  171. wchar_t *GetTag(const wchar_t *tag, const wchar_t *filename) // for simple tags
  172. {
  173. if (!_wcsicmp(tag, L"filename"))
  174. return _wcsdup(filename);
  175. else if (!_wcsicmp(tag, L"folder"))
  176. {
  177. wchar_t *folder = (wchar_t *)calloc(MAX_PATH, sizeof(wchar_t));
  178. if (folder)
  179. {
  180. lstrcpynW(folder, filename, MAX_PATH);
  181. PathRemoveFileSpecW(folder);
  182. PathRemoveBackslashW(folder);
  183. PathStripPathW(folder);
  184. return folder;
  185. }
  186. }
  187. return 0;
  188. }
  189. wchar_t *GetExtendedTag(const wchar_t *tag, const wchar_t *filename) //return 0 if not found
  190. {
  191. wchar_t buf[1024] = {0};
  192. if (!_wcsicmp(tag, L"tracknumber"))
  193. tag = L"track";
  194. #if 0
  195. if (in_get_extended_fileinfo(filename, tag, buf, sizeof(buf)) && buf[0])
  196. return _strdup(buf);
  197. #else
  198. extendedFileInfoStructW s = {filename, tag, buf, 1024};
  199. if (SendMessageW(hMainWindow, WM_WA_IPC, (WPARAM)&s, IPC_GET_EXTENDED_FILE_INFOW_HOOKABLE) && buf[0])
  200. return _wcsdup(buf);
  201. #endif
  202. return 0;
  203. }
  204. } // namespace Winamp
  205. /* --- ExternalTagProvider ---
  206. maybe we'll move this to a separate file once it's done
  207. */
  208. ExternalTagProvider::ExternalTagProvider(GetTagFunc getter, FreeTagFunc freer, void *context)
  209. : externalGetTag(getter), externalFreeTag(freer), externalContext(context)
  210. {
  211. }
  212. wchar_t *ExternalTagProvider::GetTag(const wchar_t *name, ifc_tagparams *parameters)
  213. {
  214. if (externalGetTag)
  215. {
  216. char *tag = externalGetTag(AutoChar(name), externalContext);
  217. if (tag == reinterpret_cast<char *>(-1))
  218. return 0;
  219. int size = MultiByteToWideChar(CP_ACP, 0, tag, -1, 0, 0);
  220. if (!size)
  221. {
  222. if (externalFreeTag)
  223. externalFreeTag(tag, externalContext);
  224. return 0;
  225. }
  226. wchar_t *wide = (wchar_t *)calloc(size, sizeof(wchar_t));
  227. if (!MultiByteToWideChar(CP_ACP, 0, tag, -1, wide, size))
  228. {
  229. if (wide) free(wide);
  230. if (externalFreeTag)
  231. externalFreeTag(tag, externalContext);
  232. return 0;
  233. }
  234. if (externalFreeTag)
  235. externalFreeTag(tag, externalContext);
  236. return wide;
  237. }
  238. return 0;
  239. }
  240. void ExternalTagProvider::FreeTag(wchar_t *tag)
  241. {
  242. if (tag) free(tag);
  243. }
  244. #ifdef CBCLASS
  245. #undef CBCLASS
  246. #endif
  247. #define CBCLASS ExternalTagProvider
  248. START_DISPATCH;
  249. CB(IFC_TAGPROVIDER_GET_TAG, GetTag);
  250. VCB(IFC_TAGPROVIDER_FREE_TAG, FreeTag);
  251. END_DISPATCH;
  252. #undef CBCLASS
  253. /* --- ExtendedTagProvider ---
  254. maybe we'll move this to a separate file once it's done
  255. */
  256. ExtendedTagProvider::ExtendedTagProvider(const wchar_t *_filename, GetTagFuncW getter, FreeTagFuncW freer, void *context, bool _useExtendedInfo)
  257. : externalGetTag(getter), externalFreeTag(freer), externalContext(context), filename(_filename), useExtendedInfo(_useExtendedInfo)
  258. {
  259. }
  260. wchar_t *ExtendedTagProvider::GetTag(const wchar_t *name, ifc_tagparams *parameters)
  261. {
  262. wchar_t *tag=0;
  263. if (externalGetTag)
  264. tag=externalGetTag(name, externalContext);
  265. if (tag) // if we got a tag, we'll need to make a copy, because we won't be able to tell where it came from when it's time to free it
  266. {
  267. if (tag == reinterpret_cast<wchar_t *>(-1))
  268. return 0;
  269. wchar_t *temp = *tag?_wcsdup(tag):0;
  270. if (externalFreeTag)
  271. externalFreeTag(tag, externalContext);
  272. return temp;
  273. }
  274. else
  275. {
  276. tag = Winamp::GetTag(name, filename);
  277. if (tag == reinterpret_cast<wchar_t *>(-1))
  278. return 0;
  279. if (!tag && useExtendedInfo)
  280. tag = Winamp::GetExtendedTag(name, filename);
  281. if (tag == reinterpret_cast<wchar_t *>(-1))
  282. return 0;
  283. return tag;
  284. }
  285. }
  286. void ExtendedTagProvider::FreeTag(char *tag)
  287. {
  288. if (tag) free(tag);
  289. }
  290. #ifdef CBCLASS
  291. #undef CBCLASS
  292. #endif
  293. #define CBCLASS ExtendedTagProvider
  294. START_DISPATCH;
  295. CB(IFC_TAGPROVIDER_GET_TAG, GetTag);
  296. VCB(IFC_TAGPROVIDER_FREE_TAG, FreeTag);
  297. END_DISPATCH;
  298. #undef CBCLASS
  299. #ifdef CBCLASS
  300. #undef CBCLASS
  301. #endif
  302. #define CBCLASS TagParameters
  303. START_DISPATCH;
  304. CB(IFC_TAGPARAMS_GETPARAMETER, GetParameter);
  305. END_DISPATCH;
  306. #undef CBCLASS