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