Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

269 lines
6.6KB

  1. #include <windows.h>
  2. #include "iasiodrv.h"
  3. #include "asiolist.h"
  4. #define ASIODRV_DESC "description"
  5. #define INPROC_SERVER "InprocServer32"
  6. #define ASIO_PATH "software\\asio"
  7. #define COM_CLSID "clsid"
  8. // ******************************************************************
  9. // Local Functions
  10. // ******************************************************************
  11. static LONG findDrvPath (char *clsidstr,char *dllpath,int dllpathsize)
  12. {
  13. HKEY hkEnum,hksub,hkpath;
  14. char databuf[512];
  15. LONG cr,rc = -1;
  16. DWORD datatype,datasize;
  17. DWORD index;
  18. OFSTRUCT ofs;
  19. HFILE hfile;
  20. BOOL found = FALSE;
  21. CharLowerBuff(clsidstr,strlen(clsidstr));
  22. if ((cr = RegOpenKey(HKEY_CLASSES_ROOT,COM_CLSID,&hkEnum)) == ERROR_SUCCESS) {
  23. index = 0;
  24. while (cr == ERROR_SUCCESS && !found) {
  25. cr = RegEnumKey(hkEnum,index++,(LPTSTR)databuf,512);
  26. if (cr == ERROR_SUCCESS) {
  27. CharLowerBuff(databuf,strlen(databuf));
  28. if (!(strcmp(databuf,clsidstr))) {
  29. if ((cr = RegOpenKeyEx(hkEnum,(LPCTSTR)databuf,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {
  30. if ((cr = RegOpenKeyEx(hksub,(LPCTSTR)INPROC_SERVER,0,KEY_READ,&hkpath)) == ERROR_SUCCESS) {
  31. datatype = REG_SZ; datasize = (DWORD)dllpathsize;
  32. cr = RegQueryValueEx(hkpath,0,0,&datatype,(LPBYTE)dllpath,&datasize);
  33. if (cr == ERROR_SUCCESS) {
  34. memset(&ofs,0,sizeof(OFSTRUCT));
  35. ofs.cBytes = sizeof(OFSTRUCT);
  36. hfile = OpenFile(dllpath,&ofs,OF_EXIST);
  37. if (hfile) rc = 0;
  38. }
  39. RegCloseKey(hkpath);
  40. }
  41. RegCloseKey(hksub);
  42. }
  43. found = TRUE; // break out
  44. }
  45. }
  46. }
  47. RegCloseKey(hkEnum);
  48. }
  49. return rc;
  50. }
  51. static LPASIODRVSTRUCT newDrvStruct (HKEY hkey,char *keyname,int drvID,LPASIODRVSTRUCT lpdrv)
  52. {
  53. HKEY hksub;
  54. char databuf[256];
  55. char dllpath[MAXPATHLEN];
  56. WORD wData[100];
  57. CLSID clsid;
  58. DWORD datatype,datasize;
  59. LONG cr,rc;
  60. if (!lpdrv) {
  61. if ((cr = RegOpenKeyEx(hkey,(LPCTSTR)keyname,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {
  62. datatype = REG_SZ; datasize = 256;
  63. cr = RegQueryValueEx(hksub,COM_CLSID,0,&datatype,(LPBYTE)databuf,&datasize);
  64. if (cr == ERROR_SUCCESS) {
  65. rc = findDrvPath (databuf,dllpath,MAXPATHLEN);
  66. if (rc == 0) {
  67. lpdrv = new ASIODRVSTRUCT[1];
  68. if (lpdrv) {
  69. memset(lpdrv,0,sizeof(ASIODRVSTRUCT));
  70. lpdrv->drvID = drvID;
  71. MultiByteToWideChar(CP_ACP,0,(LPCSTR)databuf,-1,(LPWSTR)wData,100);
  72. if ((cr = CLSIDFromString((LPOLESTR)wData,(LPCLSID)&clsid)) == S_OK) {
  73. memcpy(&lpdrv->clsid,&clsid,sizeof(CLSID));
  74. }
  75. datatype = REG_SZ; datasize = 256;
  76. cr = RegQueryValueEx(hksub,ASIODRV_DESC,0,&datatype,(LPBYTE)databuf,&datasize);
  77. if (cr == ERROR_SUCCESS) {
  78. strcpy(lpdrv->drvname,databuf);
  79. }
  80. else strcpy(lpdrv->drvname,keyname);
  81. }
  82. }
  83. }
  84. RegCloseKey(hksub);
  85. }
  86. }
  87. else lpdrv->next = newDrvStruct(hkey,keyname,drvID+1,lpdrv->next);
  88. return lpdrv;
  89. }
  90. static void deleteDrvStruct (LPASIODRVSTRUCT lpdrv)
  91. {
  92. IASIO *iasio;
  93. if (lpdrv != 0) {
  94. deleteDrvStruct(lpdrv->next);
  95. if (lpdrv->asiodrv) {
  96. iasio = (IASIO *)lpdrv->asiodrv;
  97. iasio->Release();
  98. }
  99. delete lpdrv;
  100. }
  101. }
  102. static LPASIODRVSTRUCT getDrvStruct (int drvID,LPASIODRVSTRUCT lpdrv)
  103. {
  104. while (lpdrv) {
  105. if (lpdrv->drvID == drvID) return lpdrv;
  106. lpdrv = lpdrv->next;
  107. }
  108. return 0;
  109. }
  110. // ******************************************************************
  111. // ******************************************************************
  112. // AsioDriverList
  113. // ******************************************************************
  114. AsioDriverList::AsioDriverList ()
  115. {
  116. HKEY hkEnum = 0;
  117. char keyname[MAXDRVNAMELEN];
  118. LPASIODRVSTRUCT pdl;
  119. LONG cr;
  120. DWORD index = 0;
  121. BOOL fin = FALSE;
  122. numdrv = 0;
  123. lpdrvlist = 0;
  124. cr = RegOpenKey(HKEY_LOCAL_MACHINE,ASIO_PATH,&hkEnum);
  125. while (cr == ERROR_SUCCESS) {
  126. if ((cr = RegEnumKey(hkEnum,index++,(LPTSTR)keyname,MAXDRVNAMELEN))== ERROR_SUCCESS) {
  127. lpdrvlist = newDrvStruct (hkEnum,keyname,0,lpdrvlist);
  128. }
  129. else fin = TRUE;
  130. }
  131. if (hkEnum) RegCloseKey(hkEnum);
  132. pdl = lpdrvlist;
  133. while (pdl) {
  134. numdrv++;
  135. pdl = pdl->next;
  136. }
  137. if (numdrv) CoInitialize(0); // initialize COM
  138. }
  139. AsioDriverList::~AsioDriverList ()
  140. {
  141. if (numdrv) {
  142. deleteDrvStruct(lpdrvlist);
  143. CoUninitialize();
  144. }
  145. }
  146. LONG AsioDriverList::asioGetNumDev (VOID)
  147. {
  148. return (LONG)numdrv;
  149. }
  150. LONG AsioDriverList::asioOpenDriver (int drvID,LPVOID *asiodrv)
  151. {
  152. LPASIODRVSTRUCT lpdrv = 0;
  153. long rc;
  154. if (!asiodrv) return DRVERR_INVALID_PARAM;
  155. if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
  156. if (!lpdrv->asiodrv) {
  157. rc = CoCreateInstance(lpdrv->clsid,0,CLSCTX_INPROC_SERVER,lpdrv->clsid,asiodrv);
  158. if (rc == S_OK) {
  159. lpdrv->asiodrv = *asiodrv;
  160. return 0;
  161. }
  162. // else if (rc == REGDB_E_CLASSNOTREG)
  163. // strcpy (info->messageText, "Driver not registered in the Registration Database!");
  164. }
  165. else rc = DRVERR_DEVICE_ALREADY_OPEN;
  166. }
  167. else rc = DRVERR_DEVICE_NOT_FOUND;
  168. return rc;
  169. }
  170. LONG AsioDriverList::asioCloseDriver (int drvID)
  171. {
  172. LPASIODRVSTRUCT lpdrv = 0;
  173. IASIO *iasio;
  174. if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
  175. if (lpdrv->asiodrv) {
  176. iasio = (IASIO *)lpdrv->asiodrv;
  177. iasio->Release();
  178. lpdrv->asiodrv = 0;
  179. }
  180. }
  181. return 0;
  182. }
  183. LONG AsioDriverList::asioGetDriverName (int drvID,char *drvname,int drvnamesize)
  184. {
  185. LPASIODRVSTRUCT lpdrv = 0;
  186. if (!drvname) return DRVERR_INVALID_PARAM;
  187. if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
  188. if (strlen(lpdrv->drvname) < (unsigned int)drvnamesize) {
  189. strcpy(drvname,lpdrv->drvname);
  190. }
  191. else {
  192. memcpy(drvname,lpdrv->drvname,drvnamesize-4);
  193. drvname[drvnamesize-4] = '.';
  194. drvname[drvnamesize-3] = '.';
  195. drvname[drvnamesize-2] = '.';
  196. drvname[drvnamesize-1] = 0;
  197. }
  198. return 0;
  199. }
  200. return DRVERR_DEVICE_NOT_FOUND;
  201. }
  202. LONG AsioDriverList::asioGetDriverPath (int drvID,char *dllpath,int dllpathsize)
  203. {
  204. LPASIODRVSTRUCT lpdrv = 0;
  205. if (!dllpath) return DRVERR_INVALID_PARAM;
  206. if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
  207. if (strlen(lpdrv->dllpath) < (unsigned int)dllpathsize) {
  208. strcpy(dllpath,lpdrv->dllpath);
  209. return 0;
  210. }
  211. dllpath[0] = 0;
  212. return DRVERR_INVALID_PARAM;
  213. }
  214. return DRVERR_DEVICE_NOT_FOUND;
  215. }
  216. LONG AsioDriverList::asioGetDriverCLSID (int drvID,CLSID *clsid)
  217. {
  218. LPASIODRVSTRUCT lpdrv = 0;
  219. if (!clsid) return DRVERR_INVALID_PARAM;
  220. if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
  221. memcpy(clsid,&lpdrv->clsid,sizeof(CLSID));
  222. return 0;
  223. }
  224. return DRVERR_DEVICE_NOT_FOUND;
  225. }