AlbumArt.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. #include "mp4.h"
  2. #include "AlbumArt.h"
  3. #include "api__in_mp4.h"
  4. #include "main.h"
  5. #include "../nu/AutoWide.h"
  6. #include "VirtualIO.h"
  7. #include "Stopper.h"
  8. #include <shlwapi.h>
  9. #include <strsafe.h>
  10. bool IsMyExtension(const wchar_t *filename)
  11. {
  12. const wchar_t *extension = PathFindExtension(filename);
  13. if (extension && *extension)
  14. {
  15. wchar_t exts[1024] = L"";
  16. // TODO: build a copy of this at config load time so we don't have to run this every time
  17. GetPrivateProfileStringW(L"in_mp4", L"extensionlist", defaultExtensions, exts, 1024, m_ini);
  18. extension++;
  19. wchar_t *b = exts;
  20. wchar_t *c = 0;
  21. do
  22. {
  23. wchar_t d[20] = {0};
  24. StringCchCopyW(d, 15, b);
  25. c = wcschr(b, L';');
  26. if (c)
  27. {
  28. if ((c-b)<15)
  29. d[c - b] = 0;
  30. }
  31. if (!_wcsicmp(extension, d))
  32. return true;
  33. b = c + 1;
  34. }
  35. while (c);
  36. }
  37. return false;
  38. }
  39. bool MP4_AlbumArtProvider::IsMine(const wchar_t *filename)
  40. {
  41. return IsMyExtension(filename);
  42. }
  43. int MP4_AlbumArtProvider::ProviderType()
  44. {
  45. return ALBUMARTPROVIDER_TYPE_EMBEDDED;
  46. }
  47. static int MimeTypeToFlags(const wchar_t *mime_type)
  48. {
  49. if (!mime_type)
  50. return 0;
  51. if (!_wcsicmp(mime_type, L"jpeg")
  52. || !_wcsicmp(mime_type, L"jpg")
  53. || !_wcsicmp(mime_type, L"image/jpeg")
  54. || !_wcsicmp(mime_type, L"image/jpg"))
  55. return 13; /* JPEG */
  56. if (!_wcsicmp(mime_type, L"png")
  57. || !_wcsicmp(mime_type, L"image/png"))
  58. return 14; /* PNG */
  59. if (!_wcsicmp(mime_type, L"gif")
  60. || !_wcsicmp(mime_type, L"image/gif"))
  61. return 12; /* GIF */
  62. if (!_wcsicmp(mime_type, L"bmp")
  63. || !_wcsicmp(mime_type, L"image/bmp"))
  64. return 27; /* BMP */
  65. return 0; /* default to binary, I guess */
  66. }
  67. int MP4_AlbumArtProvider::GetAlbumArtData(const wchar_t *filename, const wchar_t *type, void **bits, size_t *len, wchar_t **mimeType)
  68. {
  69. void *reader = CreateUnicodeReader(filename);
  70. if (!reader)
  71. return ALBUMARTPROVIDER_FAILURE;
  72. MP4FileHandle mp4 = MP4ReadEx(filename, reader, &UnicodeIO);
  73. if (!mp4)
  74. {
  75. DestroyUnicodeReader(reader);
  76. return ALBUMARTPROVIDER_FAILURE;
  77. }
  78. else
  79. {
  80. UnicodeClose(reader); // go ahead and close the file so we don't lock it
  81. }
  82. u_int8_t *art = 0;
  83. u_int32_t artSize = 0;
  84. int flags = 0;
  85. if (MP4GetMetadataCoverArt(mp4, &art, &artSize, &flags))
  86. {
  87. *bits = WASABI_API_MEMMGR->sysMalloc(artSize);
  88. memcpy(*bits, art, artSize);
  89. *len=artSize;
  90. /* TODO: use flags */
  91. *mimeType = 0; // no idea what the mime type is :(
  92. MP4Free(art);
  93. MP4Close(mp4);
  94. DestroyUnicodeReader(reader);
  95. return ALBUMARTPROVIDER_SUCCESS;
  96. }
  97. MP4Close(mp4);
  98. DestroyUnicodeReader(reader);
  99. return ALBUMARTPROVIDER_FAILURE;
  100. }
  101. int MP4_AlbumArtProvider::SetAlbumArtData(const wchar_t *filename, const wchar_t *type, void *bits, size_t len, const wchar_t *mimeType)
  102. {
  103. MP4FileHandle mp4 = MP4Modify(filename, 0, 0);
  104. if (!mp4)
  105. {
  106. return ALBUMARTPROVIDER_FAILURE;
  107. }
  108. int flags = MimeTypeToFlags(mimeType);
  109. if (MP4SetMetadataCoverArt(mp4, (u_int8_t *)bits, len, flags))
  110. {
  111. MP4Close(mp4);
  112. return ALBUMARTPROVIDER_SUCCESS;
  113. }
  114. MP4Close(mp4);
  115. return ALBUMARTPROVIDER_FAILURE;
  116. }
  117. int MP4_AlbumArtProvider::DeleteAlbumArt(const wchar_t *filename, const wchar_t *type)
  118. {
  119. MP4FileHandle mp4 = MP4Modify(filename, 0, 0);
  120. if (!mp4)
  121. {
  122. return ALBUMARTPROVIDER_FAILURE;
  123. }
  124. if (MP4DeleteMetadataCoverArt(mp4))
  125. {
  126. Stopper stopper;
  127. if (!_wcsicmp(filename, lastfn))
  128. stopper.Stop();
  129. MP4Close(mp4);
  130. stopper.Play();
  131. return ALBUMARTPROVIDER_SUCCESS;
  132. }
  133. MP4Close(mp4);
  134. return ALBUMARTPROVIDER_FAILURE;
  135. }
  136. #define CBCLASS MP4_AlbumArtProvider
  137. START_DISPATCH;
  138. CB(SVC_ALBUMARTPROVIDER_PROVIDERTYPE, ProviderType);
  139. CB(SVC_ALBUMARTPROVIDER_GETALBUMARTDATA, GetAlbumArtData);
  140. CB(SVC_ALBUMARTPROVIDER_SETALBUMARTDATA, SetAlbumArtData);
  141. CB(SVC_ALBUMARTPROVIDER_DELETEALBUMART, DeleteAlbumArt);
  142. CB(SVC_ALBUMARTPROVIDER_ISMINE, IsMine);
  143. END_DISPATCH;
  144. #undef CBCLASS
  145. static MP4_AlbumArtProvider albumArtProvider;
  146. // {315CA473-4A7B-43a9-BB1B-7E1C24B3BFE2}
  147. static const GUID mp4_albumartproviderGUID =
  148. { 0x315ca473, 0x4a7b, 0x43a9, { 0xbb, 0x1b, 0x7e, 0x1c, 0x24, 0xb3, 0xbf, 0xe2 } };
  149. FOURCC AlbumArtFactory::GetServiceType()
  150. {
  151. return svc_albumArtProvider::SERVICETYPE;
  152. }
  153. const char *AlbumArtFactory::GetServiceName()
  154. {
  155. return "MP4 Album Art Provider";
  156. }
  157. GUID AlbumArtFactory::GetGUID()
  158. {
  159. return mp4_albumartproviderGUID;
  160. }
  161. void *AlbumArtFactory::GetInterface(int global_lock)
  162. {
  163. return &albumArtProvider;
  164. }
  165. int AlbumArtFactory::SupportNonLockingInterface()
  166. {
  167. return 1;
  168. }
  169. int AlbumArtFactory::ReleaseInterface(void *ifc)
  170. {
  171. //plugin.service->service_unlock(ifc);
  172. return 1;
  173. }
  174. const char *AlbumArtFactory::GetTestString()
  175. {
  176. return 0;
  177. }
  178. int AlbumArtFactory::ServiceNotify(int msg, int param1, int param2)
  179. {
  180. return 1;
  181. }
  182. #ifdef CBCLASS
  183. #undef CBCLASS
  184. #endif
  185. #define CBCLASS AlbumArtFactory
  186. START_DISPATCH;
  187. CB(WASERVICEFACTORY_GETSERVICETYPE, GetServiceType)
  188. CB(WASERVICEFACTORY_GETSERVICENAME, GetServiceName)
  189. CB(WASERVICEFACTORY_GETGUID, GetGUID)
  190. CB(WASERVICEFACTORY_GETINTERFACE, GetInterface)
  191. CB(WASERVICEFACTORY_SUPPORTNONLOCKINGGETINTERFACE, SupportNonLockingInterface)
  192. CB(WASERVICEFACTORY_RELEASEINTERFACE, ReleaseInterface)
  193. CB(WASERVICEFACTORY_GETTESTSTRING, GetTestString)
  194. CB(WASERVICEFACTORY_SERVICENOTIFY, ServiceNotify)
  195. END_DISPATCH;