PmpDevice.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. #include "main.h"
  2. #include "DeviceView.h"
  3. #include "api__ml_pmp.h"
  4. #include "../nu/refcount.h"
  5. #include "..\..\General\gen_ml/ml_ipc_0313.h"
  6. #include "DeviceCommands.h"
  7. #include "resource1.h"
  8. #include <strsafe.h>
  9. // known commands
  10. static const char *DEVICE_CMD_VIEW_OPEN = "view_open";
  11. static const char *DEVICE_CMD_SYNC = "sync";
  12. static const char *DEVICE_CMD_AUTOFILL = "autofill";
  13. static const char *DEVICE_CMD_PLAYLIST_CREATE = "playlist_create";
  14. static const char *DEVICE_CMD_RENAME = "rename";
  15. static const char *DEVICE_CMD_PREFERENCES = "preferences";
  16. static const char *DEVICE_CMD_EJECT = "eject";
  17. static const char *DEVICE_CMD_REMOVE = "remove";
  18. static const char *DEVICE_CMD_TRANSFER = "transfer";
  19. static const char *DEVICE_CMD_HIDE = "hide";
  20. extern void UpdateDevicesListView(bool softUpdate);
  21. // we're going to share the command enum stuff for all devices
  22. class PortableDeviceType : public ifc_devicetype
  23. {
  24. public:
  25. PortableDeviceType()
  26. {
  27. }
  28. const char *GetName()
  29. {
  30. return "portable";
  31. }
  32. HRESULT GetIcon(wchar_t *buffer, size_t bufferSize, int width, int height)
  33. {
  34. return E_NOTIMPL;
  35. }
  36. HRESULT GetDisplayName(wchar_t *buffer, size_t bufferSize)
  37. {
  38. if (NULL == buffer)
  39. return E_POINTER;
  40. WASABI_API_LNGSTRINGW_BUF(IDS_PORTABLE_DEVICE_TYPE, buffer, bufferSize);
  41. return S_OK;
  42. }
  43. protected:
  44. #define CBCLASS PortableDeviceType
  45. START_DISPATCH_INLINE;
  46. CB(API_GETNAME, GetName);
  47. CB(API_GETICON, GetIcon);
  48. CB(API_GETDISPLAYNAME, GetDisplayName);
  49. END_DISPATCH;
  50. #undef CBCLASS
  51. };
  52. class USBDeviceConnection : public ifc_deviceconnection
  53. {
  54. public:
  55. USBDeviceConnection()
  56. {
  57. }
  58. const char *GetName()
  59. {
  60. return "usb";
  61. }
  62. HRESULT GetIcon(wchar_t *buffer, size_t bufferSize, int width, int height)
  63. {
  64. if (FALSE == FormatResProtocol(MAKEINTRESOURCE(IDB_USB),
  65. L"PNG", buffer, bufferSize))
  66. {
  67. return E_FAIL;
  68. }
  69. return S_OK;
  70. }
  71. HRESULT GetDisplayName(wchar_t *buffer, size_t bufferSize)
  72. {
  73. if (NULL == buffer)
  74. return E_POINTER;
  75. WASABI_API_LNGSTRINGW_BUF(IDS_DEVICE_CONNECTION_USB, buffer, bufferSize);
  76. return S_OK;
  77. }
  78. protected:
  79. #define CBCLASS USBDeviceConnection
  80. START_DISPATCH_INLINE;
  81. CB(API_GETNAME, GetName);
  82. CB(API_GETICON, GetIcon);
  83. CB(API_GETDISPLAYNAME, GetDisplayName);
  84. END_DISPATCH;
  85. #undef CBCLASS
  86. };
  87. static PortableDeviceType portable_device_type;
  88. static USBDeviceConnection usb_connection;
  89. static PortableCommand registered_commands[] =
  90. {
  91. PortableCommand(DEVICE_CMD_VIEW_OPEN, IDS_DEVICE_CMD_VIEW_OPEN, IDS_DEVICE_CMD_VIEW_OPEN_DESC),
  92. PortableCommand(DEVICE_CMD_SYNC, IDS_DEVICE_CMD_SYNC, IDS_DEVICE_CMD_SYNC_DESC),
  93. PortableCommand(DEVICE_CMD_TRANSFER, IDS_DEVICE_CMD_TRANSFER, IDS_DEVICE_CMD_TRANSFER_DESC),
  94. PortableCommand(DEVICE_CMD_EJECT, IDS_DEVICE_CMD_EJECT, IDS_DEVICE_CMD_EJECT_DESC),
  95. PortableCommand(DEVICE_CMD_REMOVE, IDS_DEVICE_CMD_REMOVE, IDS_DEVICE_CMD_REMOVE_DESC),
  96. PortableCommand(DEVICE_CMD_RENAME, IDS_DEVICE_CMD_RENAME, IDS_DEVICE_CMD_RENAME_DESC),
  97. PortableCommand(DEVICE_CMD_AUTOFILL, IDS_DEVICE_CMD_AUTOFILL, IDS_DEVICE_CMD_AUTOFILL_DESC),
  98. PortableCommand(DEVICE_CMD_PLAYLIST_CREATE, IDS_DEVICE_CMD_PLAYLIST_CREATE, IDS_DEVICE_CMD_PLAYLIST_CREATE_DESC),
  99. PortableCommand(DEVICE_CMD_PREFERENCES, IDS_DEVICE_CMD_PREFERENCES, IDS_DEVICE_CMD_PREFERENCES_DESC),
  100. PortableCommand(DEVICE_CMD_HIDE, IDS_DEVICE_CMD_HIDE, IDS_DEVICE_CMD_HIDE),
  101. };
  102. static ifc_devicecommand * _cdecl
  103. Devices_RegisterCommand(const char *name, void *user)
  104. {
  105. for(size_t i = 0; i < sizeof(registered_commands)/sizeof(*registered_commands); i++)
  106. {
  107. if (name == registered_commands[i].GetName())
  108. {
  109. return &registered_commands[i];
  110. }
  111. }
  112. return NULL;
  113. }
  114. void Devices_Init()
  115. {
  116. if (AGAVE_API_DEVICEMANAGER)
  117. {
  118. /* register 'portable' device type */
  119. ifc_devicetype *type = &portable_device_type;
  120. AGAVE_API_DEVICEMANAGER->TypeRegister(&type, 1);
  121. /* register 'usb' connection type */
  122. ifc_deviceconnection *connection = &usb_connection;
  123. AGAVE_API_DEVICEMANAGER->ConnectionRegister(&connection, 1);
  124. /* register commands */
  125. const char *commands[sizeof(registered_commands)/sizeof(*registered_commands)];
  126. for(size_t i = 0; i < sizeof(registered_commands)/sizeof(*registered_commands); i++)
  127. {
  128. commands[i] = registered_commands[i].GetName();
  129. }
  130. AGAVE_API_DEVICEMANAGER->CommandRegisterIndirect(commands, sizeof(registered_commands)/sizeof(*registered_commands), Devices_RegisterCommand, NULL);
  131. }
  132. }
  133. int DeviceView::QueryInterface(GUID interface_guid, void **object)
  134. {
  135. if (interface_guid == IFC_Device)
  136. {
  137. AddRef();
  138. *object = (ifc_device *)this;
  139. return 0;
  140. }
  141. return 1;
  142. }
  143. const char *DeviceView::GetName()
  144. {
  145. return name;
  146. }
  147. HRESULT DeviceView::GetIcon(wchar_t *buffer, size_t bufferSize, int width, int height)
  148. {
  149. buffer[0]=0;
  150. dev->extraActions(DEVICE_GET_ICON, width, height, (intptr_t)buffer);
  151. if (buffer[0] == 0)
  152. return E_NOTIMPL;
  153. else
  154. return S_OK;
  155. return E_NOTIMPL;
  156. }
  157. HRESULT DeviceView::GetDisplayName(wchar_t *buffer, size_t bufferSize)
  158. {
  159. // TODO sometimes this is erroring on loading
  160. dev->getPlaylistName(0, buffer, bufferSize);
  161. return S_OK;
  162. }
  163. const char *DeviceView::GetType()
  164. {
  165. return "portable";
  166. }
  167. const char *DeviceView::GetDisplayType()
  168. {
  169. return display_type;
  170. }
  171. const char *DeviceView::GetConnection()
  172. {
  173. return connection_type;
  174. }
  175. BOOL DeviceView::GetHidden()
  176. {
  177. return FALSE;
  178. }
  179. HRESULT DeviceView::GetTotalSpace(uint64_t *size)
  180. {
  181. UpdateSpaceInfo(FALSE, TRUE);
  182. *size = dev->getDeviceCapacityTotal();
  183. return S_OK;
  184. }
  185. HRESULT DeviceView::GetUsedSpace(uint64_t *size)
  186. {
  187. if (NULL == size)
  188. return E_POINTER;
  189. UpdateSpaceInfo(TRUE, TRUE);
  190. *size = usedSpace;
  191. return S_OK;
  192. }
  193. BOOL DeviceView::GetAttached()
  194. {
  195. return TRUE; // ml_pmp devices are by default attached
  196. }
  197. HRESULT DeviceView::Attach(HWND hostWindow)
  198. {
  199. return E_NOTIMPL;
  200. }
  201. HRESULT DeviceView::Detach(HWND hostWindow)
  202. {
  203. return E_NOTIMPL;
  204. }
  205. HRESULT DeviceView::EnumerateCommands(ifc_devicesupportedcommandenum **enumerator, DeviceCommandContext context)
  206. {
  207. DeviceCommandInfo commands[32];
  208. size_t count;
  209. if (NULL == enumerator)
  210. return E_POINTER;
  211. count = 0;
  212. LinkedQueue * txQueue = getTransferQueue(this);
  213. if (txQueue == NULL)
  214. return E_POINTER;
  215. // return E_NOTIMPL;
  216. if (context == DeviceCommandContext_View)
  217. {
  218. if (0 == txQueue->GetSize())
  219. {
  220. SetDeviceCommandInfo(&commands[count++], DEVICE_CMD_SYNC, DeviceCommandFlag_Primary);
  221. SetDeviceCommandInfo(&commands[count++], DEVICE_CMD_AUTOFILL, DeviceCommandFlag_None);
  222. SetDeviceCommandInfo(&commands[count++], DEVICE_CMD_PLAYLIST_CREATE, DeviceCommandFlag_None);
  223. SetDeviceCommandInfo(&commands[count++], DEVICE_CMD_PREFERENCES, DeviceCommandFlag_None);
  224. SetDeviceCommandInfo(&commands[count++], DEVICE_CMD_EJECT, DeviceCommandFlag_None);
  225. SetDeviceCommandInfo(&commands[count++], DEVICE_CMD_REMOVE, DeviceCommandFlag_None);
  226. }
  227. }
  228. else
  229. {
  230. SetDeviceCommandInfo(&commands[count++], DEVICE_CMD_VIEW_OPEN, DeviceCommandFlag_Primary);
  231. DeviceCommandFlags flags = DeviceCommandFlag_None;
  232. if (0 != txQueue->GetSize())
  233. flags |= DeviceCommandFlag_Disabled;
  234. if (0 != dev->extraActions(DEVICE_SYNC_UNSUPPORTED,0,0,0))
  235. flags |= DeviceCommandFlag_Disabled;
  236. SetDeviceCommandInfo(&commands[count++], (!isCloudDevice ? DEVICE_CMD_SYNC : DEVICE_CMD_TRANSFER), flags | DeviceCommandFlag_Group);
  237. if (!isCloudDevice) SetDeviceCommandInfo(&commands[count++], DEVICE_CMD_AUTOFILL, flags);
  238. flags = DeviceCommandFlag_None;
  239. if (0 == dev->extraActions(DEVICE_PLAYLISTS_UNSUPPORTED,0,0,0))
  240. {
  241. // TODO remove once we've got cloud playlists implemented
  242. if (!isCloudDevice)
  243. SetDeviceCommandInfo(&commands[count++], DEVICE_CMD_PLAYLIST_CREATE, flags | DeviceCommandFlag_Group);
  244. }
  245. // adds a specific menu item to hide the 'local library' source
  246. if (isCloudDevice)
  247. {
  248. char name[128] = {0};
  249. if (dev->extraActions(DEVICE_GET_UNIQUE_ID, (intptr_t)name, sizeof(name), 0))
  250. {
  251. if (!strcmp(name, "local_desktop"))
  252. {
  253. flags = DeviceCommandFlag_None | DeviceCommandFlag_Group;
  254. SetDeviceCommandInfo(&commands[count++], DEVICE_CMD_HIDE, flags);
  255. }
  256. }
  257. }
  258. bool has_rename = true;
  259. flags = DeviceCommandFlag_None;
  260. if (0 == dev->extraActions(DEVICE_CAN_RENAME_DEVICE,0,0,0))
  261. has_rename = false;
  262. else
  263. SetDeviceCommandInfo(&commands[count++], DEVICE_CMD_RENAME, flags | DeviceCommandFlag_Group);
  264. flags = (!has_rename ? DeviceCommandFlag_Group : DeviceCommandFlag_None);
  265. SetDeviceCommandInfo(&commands[count++], DEVICE_CMD_PREFERENCES, flags);
  266. if (!dev->extraActions(DEVICE_DOES_NOT_SUPPORT_REMOVE,0,0,0))
  267. SetDeviceCommandInfo(&commands[count++], (!isCloudDevice ? DEVICE_CMD_EJECT : DEVICE_CMD_REMOVE), flags | DeviceCommandFlag_Group);
  268. }
  269. *enumerator = new DeviceCommandEnumerator(commands, count);
  270. if (NULL == *enumerator)
  271. return E_OUTOFMEMORY;
  272. return S_OK;
  273. }
  274. HRESULT DeviceView::SendCommand(const char *command, HWND hostWindow, ULONG_PTR param)
  275. {
  276. if (!strcmp(command, DEVICE_CMD_EJECT) || !strcmp(command, DEVICE_CMD_REMOVE))
  277. {
  278. Eject();
  279. return S_OK;
  280. }
  281. else if (!strcmp(command, DEVICE_CMD_SYNC) || !strcmp(command, DEVICE_CMD_TRANSFER))
  282. {
  283. if (!this->isCloudDevice) Sync();
  284. else CloudSync();
  285. return S_OK;
  286. }
  287. else if (!strcmp(command, DEVICE_CMD_AUTOFILL))
  288. {
  289. Autofill();
  290. return S_OK;
  291. }
  292. else if (!strcmp(command, DEVICE_CMD_RENAME))
  293. {
  294. if (NULL != treeItem)
  295. MLNavItem_EditTitle(plugin.hwndLibraryParent, treeItem);
  296. else
  297. RenamePlaylist(0);
  298. return S_OK;
  299. }
  300. else if (!strcmp(command, DEVICE_CMD_PLAYLIST_CREATE))
  301. {
  302. CreatePlaylist();
  303. return S_OK;
  304. }
  305. else if (!strcmp(command, DEVICE_CMD_PREFERENCES))
  306. {
  307. SENDWAIPC(plugin.hwndWinampParent, IPC_OPENPREFSTOPAGE,(WPARAM)&devPrefsPage);
  308. return S_OK;
  309. }
  310. else if (!strcmp(command, DEVICE_CMD_HIDE))
  311. {
  312. static int IPC_CLOUD_HIDE_LOCAL = -1;
  313. if (IPC_CLOUD_HIDE_LOCAL == -1)
  314. IPC_CLOUD_HIDE_LOCAL = SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&"WinampCloudLocal", IPC_REGISTER_WINAMP_IPCMESSAGE);
  315. SENDWAIPC(plugin.hwndWinampParent, IPC_CLOUD_HIDE_LOCAL, 0);
  316. return S_OK;
  317. }
  318. return E_NOTIMPL;
  319. }
  320. HRESULT DeviceView::GetCommandFlags(const char *command, DeviceCommandFlags *flags)
  321. {
  322. return E_NOTIMPL;
  323. }
  324. HRESULT DeviceView::GetActivity(ifc_deviceactivity **activity)
  325. {
  326. LinkedQueue * txQueue = getTransferQueue();
  327. if (txQueue == NULL || txQueue->GetSize() == 0)
  328. {
  329. *activity = 0;
  330. return S_FALSE;
  331. }
  332. AddRef();
  333. *activity = this;
  334. return S_OK;
  335. }
  336. HRESULT DeviceView::Advise(ifc_deviceevent *handler)
  337. {
  338. event_handlers.push_back(handler);
  339. return S_OK;
  340. }
  341. HRESULT DeviceView::Unadvise(ifc_deviceevent *handler)
  342. {
  343. //event_handlers.eraseObject(handler);
  344. auto it = std::find(event_handlers.begin(), event_handlers.end(), handler);
  345. if (it != event_handlers.end())
  346. {
  347. event_handlers.erase(it);
  348. }
  349. return S_OK;
  350. }
  351. extern C_ItemList devices;
  352. extern void UpdateDevicesListView(bool softupdate);
  353. void DeviceView::SetNavigationItem(void *navigationItem)
  354. {
  355. if (navigationItem)
  356. RegisterViews((HNAVITEM)navigationItem);
  357. }
  358. BOOL DeviceView::GetActive()
  359. {
  360. LinkedQueue * txQueue = getTransferQueue();
  361. if (txQueue == NULL || txQueue->GetSize() == 0)
  362. return FALSE;
  363. return TRUE;
  364. }
  365. BOOL DeviceView::GetCancelable()
  366. {
  367. return FALSE;
  368. }
  369. HRESULT DeviceView::GetProgress(unsigned int *percentCompleted)
  370. {
  371. LinkedQueue * txQueue = getTransferQueue();
  372. LinkedQueue * finishedTX = getFinishedTransferQueue();
  373. int txProgress = getTransferProgress();
  374. int size = (txQueue ? txQueue->GetSize() : 0);
  375. double num = (100.0 * (double)size) - (double)txProgress;
  376. double total = (double)100 * size + 100 * (finishedTX ? finishedTX->GetSize() : 0);
  377. double percent = (0 != total) ? (((total - num) * 100) / total) : 0;
  378. *percentCompleted = (unsigned int)percent;
  379. return S_OK;
  380. }
  381. HRESULT DeviceView::Activity_GetDisplayName(wchar_t *buffer, size_t bufferMax)
  382. {
  383. WASABI_API_LNGSTRINGW_BUF(IDS_TRANSFERRING, buffer, bufferMax);
  384. return S_OK;
  385. }
  386. HRESULT DeviceView::Activity_GetStatus(wchar_t *buffer, size_t bufferMax)
  387. {
  388. WASABI_API_LNGSTRINGW_BUF(IDS_TRANSFERRING_DESC, buffer, bufferMax);
  389. return S_OK;
  390. }
  391. HRESULT DeviceView::Cancel(HWND hostWindow)
  392. {
  393. // threadKillswitch = 1; // TODO: i think this is how to do it
  394. //transferContext.WaitForKill();
  395. return S_OK;
  396. }
  397. HRESULT DeviceView::GetDropSupported(unsigned int dataType)
  398. {
  399. if (dataType == ML_TYPE_ITEMRECORDLISTW
  400. || dataType == ML_TYPE_ITEMRECORDLIST
  401. || dataType == ML_TYPE_PLAYLIST
  402. || dataType == ML_TYPE_PLAYLISTS
  403. || dataType == ML_TYPE_FILENAMES
  404. || dataType == ML_TYPE_FILENAMESW)
  405. return S_OK;
  406. return E_FAIL;
  407. }
  408. HRESULT DeviceView::Drop(void *data, unsigned int dataType)
  409. {
  410. return (HRESULT)TransferFromML(dataType,data,E_FAIL,S_OK);
  411. }
  412. HRESULT DeviceView::SetDisplayName(const wchar_t *displayName, bool force = 0)
  413. {
  414. if((0 == force && 0 == dev->extraActions(DEVICE_CAN_RENAME_DEVICE,0,0,0)))
  415. return E_FAIL;
  416. dev->setPlaylistName(0, displayName);
  417. free(devPrefsPage.name);
  418. devPrefsPage.name = _wcsdup(displayName);
  419. SENDWAIPC(plugin.hwndWinampParent, IPC_UPDATE_PREFS_DLGW, (WPARAM)&devPrefsPage);
  420. DevicePropertiesChanges();
  421. UpdateDevicesListView(false);
  422. OnNameChanged(displayName);
  423. return S_OK;
  424. }
  425. HRESULT DeviceView::GetModel(wchar_t *buffer, size_t bufferSize)
  426. {
  427. if (NULL == buffer)
  428. return E_POINTER;
  429. buffer[0] = L'\0';
  430. if(0 == dev->extraActions(DEVICE_GET_MODEL, (intptr_t)buffer, bufferSize, 0))
  431. return E_NOTIMPL;
  432. return S_OK;
  433. }
  434. HRESULT DeviceView::GetStatus(wchar_t *buffer, size_t bufferSize)
  435. {
  436. return E_NOTIMPL;
  437. }
  438. #define CBCLASS DeviceView
  439. START_MULTIPATCH;
  440. START_PATCH(PATCH_IFC_DEVICE)
  441. M_CB(PATCH_IFC_DEVICE, ifc_device, QUERYINTERFACE, QueryInterface);
  442. M_CB(PATCH_IFC_DEVICE, ifc_device, API_GETNAME, GetName);
  443. M_CB(PATCH_IFC_DEVICE, ifc_device, ifc_deviceobject::API_GETDISPLAYNAME, GetDisplayName);
  444. M_CB(PATCH_IFC_DEVICE, ifc_device, API_GETICON, GetIcon);
  445. M_CB(PATCH_IFC_DEVICE, ifc_device, API_GETTYPE, GetType);
  446. M_CB(PATCH_IFC_DEVICE, ifc_device, API_GETDISPLAYTYPE, GetDisplayType);
  447. M_CB(PATCH_IFC_DEVICE, ifc_device, API_GETCONNECTION, GetConnection);
  448. M_CB(PATCH_IFC_DEVICE, ifc_device, API_GETTOTALSPACE, GetTotalSpace);
  449. M_CB(PATCH_IFC_DEVICE, ifc_device, API_GETUSEDSPACE, GetUsedSpace);
  450. M_CB(PATCH_IFC_DEVICE, ifc_device, API_ENUMERATECOMMANDS, EnumerateCommands);
  451. M_CB(PATCH_IFC_DEVICE, ifc_device, API_SENDCOMMAND, SendCommand);
  452. M_CB(PATCH_IFC_DEVICE, ifc_device, API_GETATTACHED, GetAttached);
  453. M_CB(PATCH_IFC_DEVICE, ifc_device, API_ATTACH, Attach);
  454. M_CB(PATCH_IFC_DEVICE, ifc_device, API_DETACH, Detach);
  455. M_CB(PATCH_IFC_DEVICE, ifc_device, API_ADVISE, Advise);
  456. M_CB(PATCH_IFC_DEVICE, ifc_device, API_UNADVISE, Unadvise);
  457. M_CB(PATCH_IFC_DEVICE, ifc_device, API_CREATEVIEW, CreateView);
  458. M_CB(PATCH_IFC_DEVICE, ifc_device, API_GETACTIVITY, GetActivity);
  459. M_VCB(PATCH_IFC_DEVICE, ifc_device, API_SETNAVIGATIONITEM, SetNavigationItem);
  460. M_CB(PATCH_IFC_DEVICE, ifc_device, API_GETDROPSUPPORTED, GetDropSupported);
  461. M_CB(PATCH_IFC_DEVICE, ifc_device, API_DROP, Drop);
  462. M_CB(PATCH_IFC_DEVICE, ifc_device, API_SETDISPLAYNAME, SetDisplayName);
  463. M_CB(PATCH_IFC_DEVICE, ifc_device, API_GETMODEL, GetModel);
  464. M_CB(PATCH_IFC_DEVICE, ifc_device, ifc_device::API_GETSTATUS, GetStatus);
  465. M_CB(PATCH_IFC_DEVICE, ifc_device, ADDREF, AddRef);
  466. M_CB(PATCH_IFC_DEVICE, ifc_device, RELEASE, Release);
  467. NEXT_PATCH(PATCH_IFC_DEVICEACTIVITY)
  468. M_CB(PATCH_IFC_DEVICEACTIVITY, ifc_deviceactivity, API_GETACTIVE, GetActive);
  469. M_CB(PATCH_IFC_DEVICEACTIVITY, ifc_deviceactivity, API_GETCANCELABLE, GetCancelable);
  470. M_CB(PATCH_IFC_DEVICEACTIVITY, ifc_deviceactivity, API_GETPROGRESS, GetProgress);
  471. M_CB(PATCH_IFC_DEVICEACTIVITY, ifc_deviceactivity, ifc_deviceactivity::API_GETDISPLAYNAME, Activity_GetDisplayName);
  472. M_CB(PATCH_IFC_DEVICEACTIVITY, ifc_deviceactivity, ifc_deviceactivity::API_GETSTATUS, Activity_GetStatus);
  473. M_CB(PATCH_IFC_DEVICEACTIVITY, ifc_deviceactivity, API_CANCEL, Cancel);
  474. M_CB(PATCH_IFC_DEVICEACTIVITY, ifc_deviceactivity, ADDREF, AddRef);
  475. M_CB(PATCH_IFC_DEVICEACTIVITY, ifc_deviceactivity, RELEASE, Release);
  476. END_PATCH
  477. END_MULTIPATCH;
  478. #undef CBCLASS