MediaCoreCOM.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  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 "MediaCoreCOM.h"
  10. #include "jsapi.h"
  11. enum
  12. {
  13. DISP_MEDIACORE_ISREGISTEREDEXTENSION = 777,
  14. DISP_MEDIACORE_GETMETADATA,
  15. DISP_MEDIACORE_REGISTER_CALLBACK,
  16. DISP_MEDIACORE_UNREGISTER_CALLBACK,
  17. DISP_MEDIACORE_PLAY,
  18. DISP_MEDIACORE_ENQUEUE,
  19. DISP_MEDIACORE_PAUSE,
  20. DISP_MEDIACORE_RESUME,
  21. DISP_MEDIACORE_VOLUME,
  22. };
  23. #define CHECK_ID(str, id)\
  24. if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, rgszNames[i], -1, L##str, -1))\
  25. { rgdispid[i] = id; continue; }
  26. HRESULT MediaCoreCOM::GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgdispid)
  27. {
  28. UNREFERENCED_PARAMETER(riid);
  29. bool unknowns = false;
  30. for (unsigned int i = 0;i != cNames;i++)
  31. {
  32. CHECK_ID("IsRegisteredExtension", DISP_MEDIACORE_ISREGISTEREDEXTENSION)
  33. CHECK_ID("GetMetadata", DISP_MEDIACORE_GETMETADATA)
  34. CHECK_ID("RegisterCallback", DISP_MEDIACORE_REGISTER_CALLBACK)
  35. CHECK_ID("UnregisterCallback", DISP_MEDIACORE_UNREGISTER_CALLBACK)
  36. CHECK_ID("Play", DISP_MEDIACORE_PLAY)
  37. CHECK_ID("Enqueue", DISP_MEDIACORE_ENQUEUE)
  38. CHECK_ID("Pause", DISP_MEDIACORE_PAUSE)
  39. CHECK_ID("Resume", DISP_MEDIACORE_RESUME)
  40. CHECK_ID("volume", DISP_MEDIACORE_VOLUME)
  41. rgdispid[i] = DISPID_UNKNOWN;
  42. unknowns = true;
  43. }
  44. if (unknowns)
  45. return DISP_E_UNKNOWNNAME;
  46. else
  47. return S_OK;
  48. }
  49. HRESULT MediaCoreCOM::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
  50. {
  51. UNREFERENCED_PARAMETER(itinfo);
  52. UNREFERENCED_PARAMETER(lcid);
  53. UNREFERENCED_PARAMETER(pptinfo);
  54. return E_NOTIMPL;
  55. }
  56. HRESULT MediaCoreCOM::GetTypeInfoCount(unsigned int FAR * pctinfo)
  57. {
  58. UNREFERENCED_PARAMETER(pctinfo);
  59. return E_NOTIMPL;
  60. }
  61. HRESULT MediaCoreCOM::Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, EXCEPINFO FAR * pexecinfo, unsigned int FAR *puArgErr)
  62. {
  63. UNREFERENCED_PARAMETER(riid);
  64. UNREFERENCED_PARAMETER(lcid);
  65. UNREFERENCED_PARAMETER(pexecinfo);
  66. switch (dispid)
  67. {
  68. case DISP_MEDIACORE_PLAY:
  69. {
  70. if (pdispparams->cArgs < 1 || pdispparams->cArgs > 3)
  71. return DISP_E_BADPARAMCOUNT;
  72. /* we're probably not on the main thread, so we'll have to get onto the main thread */
  73. // TODO: APC this instead of SendMessageW
  74. enqueueFileWithMetaStructW s = {0,0,0,0};
  75. SendMessageW(hMainWindow, WM_WA_IPC, 0, IPC_DELETE);
  76. switch(pdispparams->cArgs)
  77. {
  78. case 1:
  79. s.filename = pdispparams->rgvarg[0].bstrVal;
  80. break;
  81. case 2:
  82. s.filename = pdispparams->rgvarg[1].bstrVal;
  83. s.title = pdispparams->rgvarg[0].bstrVal;
  84. break;
  85. case 3:
  86. s.filename = pdispparams->rgvarg[2].bstrVal;
  87. s.title = pdispparams->rgvarg[1].bstrVal;
  88. s.length = pdispparams->rgvarg[0].lVal;
  89. break;
  90. }
  91. s.ext = NULL;
  92. SendMessageW(hMainWindow, WM_WA_IPC, (WPARAM)&s, IPC_PLAYFILEW);
  93. SendMessageW(hMainWindow, WM_WA_IPC, 0, IPC_STARTPLAY);
  94. return S_OK;
  95. }
  96. case DISP_MEDIACORE_ENQUEUE:
  97. {
  98. if (pdispparams->cArgs < 1 || pdispparams->cArgs > 3)
  99. return DISP_E_BADPARAMCOUNT;
  100. /* we're probably not on the main thread, so we'll have to get onto the main thread */
  101. // TODO: APC this instead of SendMessageW
  102. enqueueFileWithMetaStructW s = {0,0,0,0};
  103. switch(pdispparams->cArgs)
  104. {
  105. case 1:
  106. s.filename = pdispparams->rgvarg[0].bstrVal;
  107. break;
  108. case 2:
  109. s.filename = pdispparams->rgvarg[1].bstrVal;
  110. s.title = pdispparams->rgvarg[0].bstrVal;
  111. break;
  112. case 3:
  113. s.filename = pdispparams->rgvarg[2].bstrVal;
  114. s.title = pdispparams->rgvarg[1].bstrVal;
  115. s.length = pdispparams->rgvarg[0].lVal;
  116. break;
  117. }
  118. s.ext = NULL;
  119. SendMessageW( hMainWindow, WM_WA_IPC, (WPARAM)&s, IPC_ENQUEUEFILEW );
  120. return S_OK;
  121. }
  122. case DISP_MEDIACORE_ISREGISTEREDEXTENSION:
  123. {
  124. bool isReg = false;
  125. if (pdispparams->cArgs == 1)
  126. {
  127. const wchar_t *filename = pdispparams->rgvarg[0].bstrVal;
  128. int start_offs=0;
  129. In_Module *i = in_setmod_noplay(filename, &start_offs);
  130. if (i)
  131. isReg = true;
  132. }
  133. VariantInit(pvarResult);
  134. V_VT(pvarResult) = VT_BOOL;
  135. V_BOOL(pvarResult) = (false != isReg) ? VARIANT_TRUE : VARIANT_FALSE;
  136. return S_OK;
  137. }
  138. break;
  139. case DISP_MEDIACORE_GETMETADATA:
  140. JSAPI_VERIFY_METHOD(wFlags);
  141. JSAPI_VERIFY_PARAMCOUNT(pdispparams, 2);
  142. JSAPI_VERIFY_PARAMTYPE(pdispparams, 1, VT_BSTR, puArgErr);
  143. JSAPI_VERIFY_PARAMTYPE(pdispparams, 2, VT_BSTR, puArgErr);
  144. JSAPI_INIT_RESULT(pvarResult, VT_BSTR);
  145. {
  146. wchar_t buffer[4096] = {0};
  147. extendedFileInfoStructW info = {0};
  148. info.filename = JSAPI_PARAM(pdispparams, 1).bstrVal;
  149. info.metadata = JSAPI_PARAM(pdispparams, 2).bstrVal;
  150. info.ret = buffer;
  151. info.retlen = sizeof(buffer)/sizeof(*buffer);
  152. if (NULL != info.filename &&
  153. NULL != info.metadata)
  154. {
  155. if (0 == SendMessageW(hMainWindow, WM_WA_IPC, (WPARAM)&info, IPC_GET_EXTENDED_FILE_INFOW_HOOKABLE))
  156. info.ret = NULL;
  157. JSAPI_SET_RESULT(pvarResult, bstrVal, SysAllocString(info.ret));
  158. }
  159. else
  160. JSAPI_EMPTY_RESULT(pvarResult);
  161. }
  162. return S_OK;
  163. case DISP_MEDIACORE_REGISTER_CALLBACK:
  164. return coreCallbacks.RegisterFromDispParam(pdispparams, 0, puArgErr);
  165. case DISP_MEDIACORE_UNREGISTER_CALLBACK:
  166. return coreCallbacks.UnregisterFromDispParam(pdispparams, 0, puArgErr);
  167. case DISP_MEDIACORE_PAUSE:
  168. PausePlaying();
  169. return S_OK;
  170. case DISP_MEDIACORE_RESUME:
  171. UnPausePlaying();
  172. return S_OK;
  173. case DISP_MEDIACORE_VOLUME:
  174. {
  175. if (wFlags & DISPATCH_PROPERTYPUT)
  176. {
  177. JSAPI_VERIFY_PARAMCOUNT(pdispparams, 1);
  178. JSAPI_VERIFY_PARAMTYPE(pdispparams, 1, VT_I4, puArgErr);
  179. SendMessageW(hMainWindow, WM_WA_IPC, JSAPI_PARAM(pdispparams, 1).lVal, IPC_SETVOLUME);
  180. return S_OK;
  181. }
  182. else if (wFlags & DISPATCH_PROPERTYGET)
  183. {
  184. JSAPI_VERIFY_PARAMCOUNT(pdispparams, 0);
  185. VariantInit(pvarResult);
  186. V_VT(pvarResult) = VT_I4;
  187. V_I4(pvarResult) = SendMessageW(hMainWindow, WM_WA_IPC, (WPARAM)-666, IPC_SETVOLUME);
  188. return S_OK;
  189. }
  190. }
  191. break;
  192. }
  193. return DISP_E_MEMBERNOTFOUND;
  194. }
  195. STDMETHODIMP MediaCoreCOM::QueryInterface(REFIID riid, PVOID *ppvObject)
  196. {
  197. if (!ppvObject)
  198. return E_POINTER;
  199. else if (IsEqualIID(riid, IID_IDispatch))
  200. *ppvObject = (IDispatch *)this;
  201. else if (IsEqualIID(riid, IID_IUnknown))
  202. *ppvObject = this;
  203. else
  204. {
  205. *ppvObject = NULL;
  206. return E_NOINTERFACE;
  207. }
  208. AddRef();
  209. return S_OK;
  210. }
  211. ULONG MediaCoreCOM::AddRef(void)
  212. {
  213. return 0;
  214. }
  215. ULONG MediaCoreCOM::Release(void)
  216. {
  217. return 0;
  218. }
  219. void CallDispatchMethod(IDispatch *dispatch, DISPPARAMS &params, OLECHAR *name)
  220. {
  221. unsigned int ret;
  222. DISPID dispid;
  223. if (NULL == dispatch)
  224. return;
  225. if (!(config_no_visseh&8))
  226. {
  227. __try
  228. {
  229. if (SUCCEEDED(dispatch->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_SYSTEM_DEFAULT, &dispid)))
  230. dispatch->Invoke(dispid, GUID_NULL, 0, DISPATCH_METHOD, &params, 0, 0, &ret);
  231. }
  232. __except(EXCEPTION_EXECUTE_HANDLER)
  233. {
  234. }
  235. }
  236. else
  237. {
  238. if (SUCCEEDED(dispatch->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_SYSTEM_DEFAULT, &dispid)))
  239. dispatch->Invoke(dispid, GUID_NULL, 0, DISPATCH_METHOD, &params, 0, 0, &ret);
  240. }
  241. }
  242. static void Play_NotifyCb(IDispatch *dispatch, void *param)
  243. {
  244. UNREFERENCED_PARAMETER(param);
  245. DISPPARAMS params;
  246. if (NULL == dispatch)
  247. return;
  248. params.cArgs = 0;
  249. params.cNamedArgs = 0;
  250. params.rgdispidNamedArgs = 0;
  251. params.rgvarg = 0;
  252. CallDispatchMethod(dispatch, params, L"OnPlay");
  253. }
  254. struct StopNotifyParam
  255. {
  256. DISPPARAMS params;
  257. VARIANT arguments[2];
  258. StopNotifyParam(int last_time, int fullstop)
  259. {
  260. VariantInit(&arguments[0]);
  261. V_VT(&arguments[0]) = VT_BOOL;
  262. V_BOOL(&arguments[0]) = (0 != fullstop) ? VARIANT_TRUE : VARIANT_FALSE;
  263. VariantInit(&arguments[1]);
  264. V_VT(&arguments[1]) = VT_I4;
  265. V_I4(&arguments[1]) = last_time;
  266. params.cArgs = ARRAYSIZE(arguments);
  267. params.cNamedArgs = 0;
  268. params.rgdispidNamedArgs = NULL;
  269. params.rgvarg = arguments;
  270. }
  271. };
  272. static void Stop_NotifyCb(IDispatch *dispatch, void *param)
  273. {
  274. StopNotifyParam *stopParams = (StopNotifyParam*)param;
  275. if (NULL == dispatch ||
  276. NULL == stopParams)
  277. {
  278. return;
  279. }
  280. CallDispatchMethod(dispatch, stopParams->params, L"OnStop");
  281. }
  282. static void Stop_FreeCb(void *param)
  283. {
  284. StopNotifyParam *stopParam;
  285. stopParam = (StopNotifyParam*)param;
  286. if (NULL != stopParam)
  287. delete(stopParam);
  288. }
  289. static void Pause_NotifyCb(IDispatch *dispatch, void *param)
  290. {
  291. UNREFERENCED_PARAMETER(param);
  292. DISPPARAMS params;
  293. if (NULL == dispatch)
  294. return;
  295. params.cArgs = 0;
  296. params.cNamedArgs = 0;
  297. params.rgdispidNamedArgs = 0;
  298. params.rgvarg = 0;
  299. CallDispatchMethod(dispatch, params, L"OnPause");
  300. }
  301. static void Resume_NotifyCb(IDispatch *dispatch, void *param)
  302. {
  303. UNREFERENCED_PARAMETER(param);
  304. DISPPARAMS params;
  305. if (NULL == dispatch)
  306. return;
  307. params.cArgs = 0;
  308. params.cNamedArgs = 0;
  309. params.rgdispidNamedArgs = 0;
  310. params.rgvarg = 0;
  311. CallDispatchMethod(dispatch, params, L"OnResume");
  312. }
  313. void MediaCoreCOM::OnPlay()
  314. {
  315. coreCallbacks.Notify(Play_NotifyCb, NULL, NULL);
  316. }
  317. void MediaCoreCOM::OnStop(int last_time, int fullstop)
  318. {
  319. StopNotifyParam *param;
  320. param = new StopNotifyParam(last_time, fullstop);
  321. if (NULL == param)
  322. return;
  323. coreCallbacks.Notify(Stop_NotifyCb, Stop_FreeCb, param);
  324. }
  325. void MediaCoreCOM::OnPause()
  326. {
  327. coreCallbacks.Notify(Pause_NotifyCb, NULL, NULL);
  328. }
  329. void MediaCoreCOM::OnResume()
  330. {
  331. coreCallbacks.Notify(Resume_NotifyCb, NULL, NULL);
  332. }