1
0

vis.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /*
  2. LICENSE
  3. -------
  4. Copyright 2005-2013 Nullsoft, Inc.
  5. All rights reserved.
  6. Redistribution and use in source and binary forms, with or without modification,
  7. are permitted provided that the following conditions are met:
  8. * Redistributions of source code must retain the above copyright notice,
  9. this list of conditions and the following disclaimer.
  10. * Redistributions in binary form must reproduce the above copyright notice,
  11. this list of conditions and the following disclaimer in the documentation
  12. and/or other materials provided with the distribution.
  13. * Neither the name of Nullsoft nor the names of its contributors may be used to
  14. endorse or promote products derived from this software without specific prior written permission.
  15. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  16. IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  18. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  21. IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  22. OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. */
  24. #include "api__vis_milk2.h"
  25. #include <windows.h>
  26. #include "vis.h"
  27. #include "plugin.h"
  28. #include "defines.h"
  29. #include "resource.h"
  30. #include "utility.h"
  31. CPlugin g_plugin;
  32. _locale_t g_use_C_locale = 0;
  33. char keyMappings[8];
  34. bool g_bFullyExited = true;
  35. // wasabi based services for localisation support
  36. api_service *WASABI_API_SVC = 0;
  37. api_language *WASABI_API_LNG = 0;
  38. api_application *WASABI_API_APP = 0;
  39. api_syscb *WASABI_API_SYSCB = 0;
  40. HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
  41. void config(struct winampVisModule *this_mod); // configuration dialog
  42. int init(struct winampVisModule *this_mod); // initialization for module
  43. int render1(struct winampVisModule *this_mod); // rendering for module 1
  44. void quit(struct winampVisModule *this_mod); // deinitialization for module
  45. // our only plugin module in this plugin:
  46. winampVisModule mod1 =
  47. {
  48. MODULEDESC,
  49. NULL, // hwndParent
  50. NULL, // hDllInstance
  51. 0, // sRate
  52. 0, // nCh
  53. 0, // latencyMS - tells winamp how much in advance you want the audio data,
  54. // in ms.
  55. 10, // delayMS - if winamp tells the plugin to render a frame and it takes
  56. // less than this # of milliseconds, winamp will sleep (go idle)
  57. // for the remainder. In effect, this limits the framerate of
  58. // the plugin. A value of 10 would cause a fps limit of ~100.
  59. // Derivation: (1000 ms/sec) / (10 ms/frame) = 100 fps.
  60. 0, // spectrumNch
  61. 2, // waveformNch
  62. { 0, }, // spectrumData
  63. { 0, }, // waveformData
  64. config,
  65. init,
  66. render1,
  67. quit
  68. };
  69. // getmodule routine from the main header. Returns NULL if an invalid module was requested,
  70. // otherwise returns either mod1, mod2 or mod3 depending on 'which'.
  71. winampVisModule *getModule(int which)
  72. {
  73. switch (which)
  74. {
  75. case 0: return &mod1;
  76. //case 1: return &mod2;
  77. //case 2: return &mod3;
  78. default: return NULL;
  79. }
  80. }
  81. // Module header, includes version, description, and address of the module retriever function
  82. winampVisHeader hdr = { VIS_HDRVER, DLLDESC, getModule };
  83. // use this to get our own HINSTANCE since overriding DllMain(..) causes instant crashes (should see why)
  84. static HINSTANCE GetMyInstance()
  85. {
  86. MEMORY_BASIC_INFORMATION mbi = {0};
  87. if(VirtualQuery(GetMyInstance, &mbi, sizeof(mbi)))
  88. return (HINSTANCE)mbi.AllocationBase;
  89. return NULL;
  90. }
  91. // this is the only exported symbol. returns our main header.
  92. // if you are compiling C++, the extern "C" { is necessary, so we just #ifdef it
  93. #ifdef __cplusplus
  94. extern "C" {
  95. #endif
  96. __declspec( dllexport ) winampVisHeader *winampVisGetHeader(HWND hwndParent)
  97. {
  98. if(!WASABI_API_LNG_HINST)
  99. {
  100. // loader so that we can get the localisation service api for use
  101. WASABI_API_SVC = (api_service*)SendMessage(hwndParent, WM_WA_IPC, 0, IPC_GET_API_SERVICE);
  102. if (WASABI_API_SVC == (api_service*)1) WASABI_API_SVC = NULL;
  103. waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(languageApiGUID);
  104. if (sf) WASABI_API_LNG = reinterpret_cast<api_language*>(sf->getInterface());
  105. sf = WASABI_API_SVC->service_getServiceByGuid(applicationApiServiceGuid);
  106. if (sf) WASABI_API_APP = reinterpret_cast<api_application*>(sf->getInterface());
  107. sf = WASABI_API_SVC->service_getServiceByGuid(syscbApiServiceGuid);
  108. if (sf) WASABI_API_SYSCB = reinterpret_cast<api_syscb*>(sf->getInterface());
  109. // need to have this initialised before we try to do anything with localisation features
  110. WASABI_API_START_LANG(GetMyInstance(),VisMilkdropLangGUID);
  111. /* added for v2.25 as a quick work around to allow partial
  112. /* keyboard mappings (mainly coming from de-de requirements)
  113. ** [yY][Y][yY][zZ]
  114. ** 1 2 3 4
  115. **
  116. ** 1 - does yes for the 3 different prompt types
  117. ** 2 - does Ctrl+Y for stopping display of custom message of song title
  118. ** 3 - something for preset editing (not 100% sure what)
  119. ** 4 - used for the previous track sent to Winamp
  120. */
  121. WASABI_API_LNGSTRING_BUF(IDS_KEY_MAPPINGS, keyMappings, 8);
  122. // as we're under a different thread we need to set the locale
  123. //WASABI_API_LNG->UseUserNumericLocale();
  124. g_use_C_locale = WASABI_API_LNG->Get_C_NumericLocale();
  125. }
  126. return &hdr;
  127. }
  128. #ifdef __cplusplus
  129. }
  130. #endif
  131. bool WaitUntilPluginFinished(HWND hWndWinamp)
  132. {
  133. int slept = 0;
  134. while (!g_bFullyExited && slept < 1000)
  135. {
  136. Sleep(50);
  137. slept += 50;
  138. }
  139. if (!g_bFullyExited)
  140. {
  141. wchar_t title[64];
  142. MessageBoxW(hWndWinamp, WASABI_API_LNGSTRINGW(IDS_ERROR_THE_PLUGIN_IS_ALREADY_RUNNING),
  143. WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
  144. MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
  145. return false;
  146. }
  147. return true;
  148. }
  149. HWND GetDialogBoxParent(HWND winamp)
  150. {
  151. HWND parent = (HWND)SendMessage(winamp, WM_WA_IPC, 0, IPC_GETDIALOGBOXPARENT);
  152. if (!parent || parent == (HWND)1)
  153. return winamp;
  154. return parent;
  155. }
  156. // configuration. Passed this_mod, as a "this" parameter. Allows you to make one configuration
  157. // function that shares code for all your modules (you don't HAVE to use it though, you can make
  158. // config1(), config2(), etc...)
  159. void config(struct winampVisModule *this_mod)
  160. {
  161. if (!g_bFullyExited)
  162. {
  163. g_plugin.OnAltK();
  164. return;
  165. }
  166. g_bFullyExited = false;
  167. g_plugin.PluginPreInitialize(this_mod->hwndParent, this_mod->hDllInstance);
  168. WASABI_API_DIALOGBOXPARAMW(IDD_CONFIG, GetDialogBoxParent(this_mod->hwndParent), g_plugin.ConfigDialogProc, (LPARAM)&g_plugin);
  169. g_bFullyExited = true;
  170. }
  171. int (*warand)(void) = 0;
  172. int fallback_rand_fn(void) {
  173. return rand();
  174. }
  175. // initialization. Registers our window class, creates our window, etc. Again, this one works for
  176. // both modules, but you could make init1() and init2()...
  177. // returns 0 on success, 1 on failure.
  178. int init(struct winampVisModule *this_mod)
  179. {
  180. DWORD version = GetWinampVersion(mod1.hwndParent);
  181. if (!warand)
  182. {
  183. warand = (int (*)(void))SendMessage(this_mod->hwndParent, WM_WA_IPC, 0, IPC_GET_RANDFUNC);
  184. if ((size_t)warand <= 1)
  185. {
  186. warand = fallback_rand_fn;
  187. }
  188. }
  189. if (!WaitUntilPluginFinished(this_mod->hwndParent))
  190. {
  191. return 1;
  192. }
  193. if (GetWinampVersion(mod1.hwndParent) < 0x4000)
  194. {
  195. // query winamp for its playback state
  196. LRESULT ret = SendMessage(this_mod->hwndParent, WM_USER, 0, 104);
  197. // ret=1: playing, ret=3: paused, other: stopped
  198. if (ret != 1)
  199. {
  200. wchar_t title[64];
  201. MessageBoxW(this_mod->hwndParent, WASABI_API_LNGSTRINGW(IDS_THIS_PLUGIN_NEEDS_MUSIC_TO_RUN),
  202. WASABI_API_LNGSTRINGW_BUF(IDS_NO_MUSIC_PLAYING, title, 64),
  203. MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL );
  204. return 1; // failure
  205. }
  206. }
  207. g_bFullyExited = false;
  208. if (!g_plugin.PluginPreInitialize(this_mod->hwndParent, this_mod->hDllInstance))
  209. {
  210. g_plugin.PluginQuit();
  211. g_bFullyExited = true;
  212. return 1;
  213. }
  214. if (!g_plugin.PluginInitialize())
  215. {
  216. g_plugin.PluginQuit();
  217. g_bFullyExited = true;
  218. return 1;
  219. }
  220. return 0; // success
  221. }
  222. // render function for oscilliscope. Returns 0 if successful, 1 if visualization should end.
  223. int render1(struct winampVisModule *this_mod)
  224. {
  225. if (g_plugin.PluginRender(this_mod->waveformData[0], this_mod->waveformData[1]))
  226. return 0; // ok
  227. else
  228. return 1; // failed
  229. }
  230. // cleanup (opposite of init()). Should destroy the window, unregister the window class, etc.
  231. void quit(struct winampVisModule *this_mod)
  232. {
  233. g_plugin.PluginQuit();
  234. g_bFullyExited = true;
  235. }