main.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. #include "main.h"
  2. #include "api.h"
  3. #include "../Winamp/wa_ipc.h"
  4. #include "../Winamp/strutil.h"
  5. #include <shlwapi.h>
  6. #include "FLVExternalInterface.h"
  7. #include <api/service/waServiceFactory.h>
  8. #include <strsafe.h>
  9. #include "resource.h"
  10. #define SWF_PLUGIN_VERSION L"1.15"
  11. FLVExternalInterface flashExternalInterface;
  12. IVideoOutput *videoOutput=0;
  13. int playPosition=0;
  14. int playLength=-1000;
  15. api_application *WASABI_API_APP = 0;
  16. api_language *WASABI_API_LNG = 0;
  17. HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
  18. wchar_t pluginName[256] = {0}, status[256] = {0};
  19. Nullsoft::Utility::LockGuard statusGuard;
  20. template <class api_T>
  21. static void ServiceBuild(api_T *&api_t, GUID factoryGUID_t)
  22. {
  23. if (plugin.service)
  24. {
  25. waServiceFactory *factory = plugin.service->service_getServiceByGuid(factoryGUID_t);
  26. if (factory)
  27. api_t = reinterpret_cast<api_T *>( factory->getInterface() );
  28. }
  29. }
  30. template <class api_T>
  31. static void ServiceRelease(api_T *api_t, GUID factoryGUID_t)
  32. {
  33. if (plugin.service)
  34. {
  35. waServiceFactory *factory = plugin.service->service_getServiceByGuid(factoryGUID_t);
  36. if (factory)
  37. factory->releaseInterface(api_t);
  38. }
  39. api_t = NULL;
  40. }
  41. void SetFileExtensions(void)
  42. {
  43. static char fileExtensionsString[1200] = {0}; // "SWF\0Shockwave Flash Files\0"
  44. char* end = 0;
  45. StringCchCopyExA(fileExtensionsString, 1200, "SWF", &end, 0, 0);
  46. StringCchCopyExA(end+1, 1200, WASABI_API_LNGSTRING(IDS_SWF_FILES), 0, 0, 0);
  47. plugin.FileExtensions = fileExtensionsString;
  48. }
  49. int Init()
  50. {
  51. if (!IsWindow(plugin.hMainWindow))
  52. return IN_INIT_FAILURE;
  53. ServiceBuild(WASABI_API_APP, applicationApiServiceGuid);
  54. ServiceBuild(WASABI_API_LNG, languageApiGUID);
  55. WASABI_API_START_LANG(plugin.hDllInstance,InSwfLangGUID);
  56. StringCchPrintfW(pluginName,256,WASABI_API_LNGSTRINGW(IDS_NULLSOFT_SWF),SWF_PLUGIN_VERSION);
  57. plugin.description = (char*)pluginName;
  58. SetFileExtensions();
  59. return IN_INIT_SUCCESS;
  60. }
  61. void Quit()
  62. {
  63. ServiceRelease(WASABI_API_APP, applicationApiServiceGuid);
  64. ServiceRelease(WASABI_API_LNG, languageApiGUID);
  65. }
  66. void GetFileInfo(const in_char *file, in_char *title, int *length_in_ms)
  67. {
  68. if (length_in_ms)
  69. {
  70. if (file && *file)
  71. *length_in_ms=-1000;
  72. else
  73. *length_in_ms = playLength;
  74. }
  75. if (title)
  76. {
  77. if (file && *file)
  78. *title=0;
  79. else
  80. {
  81. Nullsoft::Utility::AutoLock autolock(statusGuard);
  82. if (status[0])
  83. StringCchPrintf(title, GETFILEINFO_TITLE_LENGTH, L"[%s]", status);
  84. else
  85. *title=0;
  86. }
  87. }
  88. }
  89. int InfoBox(const in_char *file, HWND hwndParent)
  90. {
  91. return INFOBOX_UNCHANGED;
  92. }
  93. int IsOurFile(const in_char *fn)
  94. {
  95. if (!_wcsnicmp(fn, L"rtmp://", 7))
  96. return 1;
  97. return 0;
  98. }
  99. static bool isFLV = false;
  100. static int PlaySWF(BSTR filename)
  101. {
  102. #ifdef WIN64
  103. if (!activeContainer || (unsigned long long)activeContainer < 65536)
  104. {
  105. isFLV = false;
  106. return 1;
  107. }
  108. #else
  109. if (!activeContainer || (unsigned long)activeContainer < 65536)
  110. {
  111. isFLV = false;
  112. return 1;
  113. }
  114. #endif
  115. isFLV = false;
  116. activeContainer->externalInterface = &flashExternalInterface;
  117. activeContainer->flash->DisableLocalSecurity();
  118. activeContainer->flash->put_BackgroundColor(0);
  119. activeContainer->flash->put_EmbedMovie(FALSE);
  120. activeContainer->flash->put_Scale(L"showAll");
  121. activeContainer->flash->put_AllowScriptAccess(L"always");
  122. HRESULT hr = activeContainer->flash->LoadMovie(0, filename);
  123. activeContainer->setVisible(TRUE);
  124. plugin.is_seekable = 0; // not seekable to start, we'll find out after opening if it's really seekable or not
  125. return 0;
  126. }
  127. static int PlayFLV(const wchar_t *filename)
  128. {
  129. #ifdef WIN64
  130. if (!activeContainer || (unsigned long long)activeContainer < 65536)
  131. {
  132. isFLV = false;
  133. return 1;
  134. }
  135. # else
  136. if (!activeContainer || (unsigned long)activeContainer < 65536)
  137. {
  138. isFLV = false;
  139. return 1;
  140. }
  141. #endif //
  142. // if (!activeContainer || (unsigned long)activeContainer < 65536)
  143. // {
  144. // isFLV = false;
  145. // return 1;
  146. // }
  147. isFLV = true;
  148. activeContainer->externalInterface = &flashExternalInterface;
  149. activeContainer->flash->DisableLocalSecurity();
  150. activeContainer->flash->put_BackgroundColor(0);
  151. activeContainer->flash->put_EmbedMovie(FALSE);
  152. activeContainer->flash->put_Scale(L"showAll");
  153. activeContainer->flash->put_AllowScriptAccess(L"always");
  154. static wchar_t pluginPath[MAX_PATH] = {0}, swfPath[MAX_PATH+7] = {0};
  155. if (!pluginPath[0] && !swfPath[0])
  156. {
  157. lstrcpynW(pluginPath, (wchar_t*)SendMessage(plugin.hMainWindow, WM_WA_IPC, 0, IPC_GETPLUGINDIRECTORYW), MAX_PATH);
  158. PathAppend(pluginPath, L"winampFLV.swf");
  159. for (wchar_t *itr = pluginPath; *itr; itr++)
  160. {
  161. if (*itr == '\\')
  162. *itr = '/';
  163. }
  164. StringCchPrintf(swfPath, MAX_PATH+7, L"file://%s", pluginPath);
  165. }
  166. HRESULT hr = activeContainer->flash->LoadMovie(0, swfPath);
  167. activeContainer->setVisible(TRUE);
  168. // TODO: make filename XML-safe
  169. wchar_t funcCall[1024] = {0};
  170. StringCchPrintf(funcCall, 1024, L"<invoke name=\"PlayFLV\" returntype=\"xml\"><arguments><string>%s</string></arguments></invoke>", filename);
  171. BSTR bstr_ret = 0;
  172. activeContainer->flash->CallFunction(funcCall, &bstr_ret);
  173. SetVolume(volume);
  174. SetPan(pan);
  175. plugin.is_seekable = 1; // not seekable to start, we'll find out after opening if it's really seekable or not
  176. return 0;
  177. }
  178. int Play(const in_char *filename)
  179. {
  180. status[0]=0;
  181. playPosition=0;
  182. playLength=-1000;
  183. if (!filename || !*filename)
  184. return 1;
  185. if (!videoOutput)
  186. videoOutput = (IVideoOutput *)SendMessage(plugin.hMainWindow,WM_WA_IPC,0,IPC_GET_IVIDEOOUTPUT);
  187. if (!videoOutput)
  188. return 1;
  189. HWND videoWnd = (HWND)videoOutput->extended(VIDUSER_GET_VIDEOHWND, 0, 0); // ask for the video hwnd
  190. wchar_t *mangledFilename = 0;
  191. if (PathIsURL(filename))
  192. mangledFilename = const_cast<wchar_t *>(filename);
  193. else
  194. {
  195. mangledFilename = (wchar_t *)malloc((MAX_PATH + 7)*sizeof(wchar_t));
  196. StringCchPrintf(mangledFilename, MAX_PATH+7, L"file://%s", filename);
  197. }
  198. videoOutput->open(0, 0, 0, 1.0, 'ENON');
  199. activeContainer = new SWFContainer(videoWnd);
  200. if (!activeContainer->flash)
  201. {
  202. delete activeContainer;
  203. activeContainer=0;
  204. if (mangledFilename != filename)
  205. free(mangledFilename);
  206. return 1; // failed
  207. }
  208. oldVidProc = (WNDPROC)(LONG_PTR)SetWindowLongPtr(videoWnd, GWLP_WNDPROC, (LONG)(LONG_PTR)WndProc);
  209. wchar_t ext[16]=L"";
  210. extension_exW(filename, ext, 16);
  211. if (!_wcsicmp(ext, L"swf"))
  212. {
  213. if (PlaySWF(mangledFilename))
  214. {
  215. return 1; // failed
  216. }
  217. }
  218. else
  219. {
  220. if (PlayFLV(mangledFilename))
  221. {
  222. return 1; // failed
  223. }
  224. }
  225. HRESULT hr = activeContainer->flash->Play();
  226. if (mangledFilename != filename)
  227. free(mangledFilename);
  228. return 0;
  229. }
  230. int localPause=0;
  231. void Pause()
  232. {
  233. localPause=1;
  234. if (isFLV)
  235. {
  236. BSTR bstr_ret;
  237. activeContainer->flash->CallFunction(L"<invoke name=\"Pause\" returntype=\"xml\"><arguments></arguments></invoke>", &bstr_ret);
  238. }
  239. }
  240. void UnPause()
  241. {
  242. localPause=0;
  243. if (isFLV)
  244. {
  245. BSTR bstr_ret;
  246. activeContainer->flash->CallFunction(L"<invoke name=\"Resume\" returntype=\"xml\"><arguments></arguments></invoke>", &bstr_ret);
  247. }
  248. }
  249. int IsPaused()
  250. {
  251. return localPause;
  252. }
  253. void Stop()
  254. {
  255. videoOutput->close();
  256. HWND videoWnd = (HWND)videoOutput->extended(VIDUSER_GET_VIDEOHWND, 0, 0); // ask for the video hwnd
  257. SetWindowLongPtr(videoWnd, GWLP_WNDPROC, (LONG)(LONG_PTR)oldVidProc);
  258. activeContainer->close();
  259. activeContainer->Release();
  260. activeContainer=0;
  261. }
  262. int GetLength()
  263. {
  264. return playLength;
  265. }
  266. int GetOutputTime()
  267. {
  268. return playPosition;
  269. }
  270. void SetOutputTime(int time_in_ms)
  271. {
  272. if (activeContainer)
  273. {
  274. if (isFLV)
  275. {
  276. double seconds = time_in_ms;
  277. seconds/=1000.0;
  278. wchar_t funcCall[1024] = {0};
  279. StringCchPrintf(funcCall, 1024, L"<invoke name=\"Seek\" returntype=\"xml\"><arguments><number>%.3f</number></arguments></invoke>", seconds);
  280. BSTR bstr_ret;
  281. activeContainer->flash->CallFunction(funcCall, &bstr_ret);
  282. }
  283. else
  284. {
  285. // TODO: maybe change the frame?
  286. }
  287. }
  288. }
  289. int pan = 0, volume = 255;
  290. void SetVolume(int _volume)
  291. {
  292. volume = _volume;
  293. if (activeContainer)
  294. {
  295. if (isFLV)
  296. {
  297. int newVolume = (volume * 100) / 255;
  298. wchar_t funcCall[1024] = {0};
  299. StringCchPrintf(funcCall, 1024, L"<invoke name=\"SetVolume\" returntype=\"xml\"><arguments><number>%u</number></arguments></invoke>", newVolume);
  300. BSTR bstr_ret;
  301. activeContainer->flash->CallFunction(funcCall, &bstr_ret);
  302. }
  303. }
  304. }
  305. void SetPan(int _pan)
  306. {
  307. pan = _pan;
  308. if (activeContainer)
  309. {
  310. if (isFLV)
  311. {
  312. int left = 100;
  313. int right = 100;
  314. if (pan < 0)
  315. left += (pan * 100)/127;
  316. if (pan>0)
  317. right-=(pan*100)/127;
  318. wchar_t funcCall[1024] = {0};
  319. StringCchPrintf(funcCall, 1024, L"<invoke name=\"SetPan\" returntype=\"xml\"><arguments><number>%u</number><number>%u</number></arguments></invoke>", left, right);
  320. BSTR bstr_ret = 0;
  321. activeContainer->flash->CallFunction(funcCall, &bstr_ret);
  322. }
  323. }
  324. }
  325. void EQSet(int on, char data[10], int preamp)
  326. {}
  327. int DoAboutMessageBox(HWND parent, wchar_t* title, wchar_t* message)
  328. {
  329. MSGBOXPARAMS msgbx = {sizeof(MSGBOXPARAMS),0};
  330. msgbx.lpszText = message;
  331. msgbx.lpszCaption = title;
  332. msgbx.lpszIcon = MAKEINTRESOURCE(102);
  333. msgbx.hInstance = GetModuleHandle(0);
  334. msgbx.dwStyle = MB_USERICON;
  335. msgbx.hwndOwner = parent;
  336. return MessageBoxIndirect(&msgbx);
  337. }
  338. void About(HWND hwndParent);
  339. In_Module plugin =
  340. {
  341. IN_VER_RET,
  342. "nullsoft(in_swf.dll)",
  343. 0,
  344. 0,
  345. 0 /*"SWF\0Shockwave Flash Files\0"*/,
  346. 1,
  347. 1,
  348. About,
  349. About,
  350. Init,
  351. Quit,
  352. GetFileInfo,
  353. InfoBox,
  354. IsOurFile,
  355. Play,
  356. Pause,
  357. UnPause,
  358. IsPaused,
  359. Stop,
  360. GetLength,
  361. GetOutputTime,
  362. SetOutputTime,
  363. SetVolume,
  364. SetPan,
  365. 0,
  366. 0,
  367. 0,
  368. 0,
  369. 0,
  370. 0,
  371. 0,
  372. 0,
  373. 0,
  374. 0,
  375. 0,
  376. EQSet,
  377. 0,
  378. 0
  379. };
  380. void About(HWND hwndParent)
  381. {
  382. wchar_t message[1024] = {0}, text[1024] = {0};
  383. WASABI_API_LNGSTRINGW_BUF(IDS_NULLSOFT_SWF_OLD,text,1024);
  384. StringCchPrintf(message, 1024, WASABI_API_LNGSTRINGW(IDS_ABOUT_TEXT),
  385. plugin.description, TEXT(__DATE__));
  386. DoAboutMessageBox(hwndParent,text,message);
  387. }
  388. extern "C" __declspec(dllexport) In_Module * winampGetInModule2()
  389. {
  390. return &plugin;
  391. }