TTKMusicPlayer  4.3.0.0
TTKMusicPlayer imitates Kugou UI, the music player uses of qmmp core library based on Qt for windows and linux
qdevicewatcher_win32.cpp
Go to the documentation of this file.
1 #include "qdevicewatcher.h"
2 #include "qdevicewatcher_p.h"
3 
4 //TODO: If wince works, use Q_OS_WIN
5 #ifdef Q_OS_WIN32
6 #include <QStringList>
7 #include <QCoreApplication>
8 
9 #undef _WIN32_WINNT
10 #define _WIN32_WINNT 0x0500
11 #include <dbt.h>
12 
13 #ifndef DBT_CUSTOMEVENT
14 # define DBT_CUSTOMEVENT 0x8006
15 #endif
16 
17 #define CONFIG_NOTIFICATION 0
18 
19 #if CONFIG_NOTIFICATION
20 static HDEVNOTIFY hDevNotify = 0;
21 #define HID_CLASSGUID {0x4d1e55b2, 0xf16f, 0x11cf,{ 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}}
22 static const GUID WceusbshGUID = { 0x25dbce51, 0x6c8f, 0x4a72, 0x8a,0x6d,0xb5,0x4c,0x2b,0x4f,0xc8,0x35 };
23 static const GUID GUID_DEVINTERFACE_USBSTOR = { 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };
24 static const GUID InterfaceClassGuid = GUID_DEVINTERFACE_USBSTOR;//(GUID)HID_CLASSGUID; //GUID_DEVINTERFACE_USBSTOR
25 #endif //CONFIG_NOTIFICATION
26 
27 static QStringList drivesFromMask(quint32 driveBits) //driveBits ->unitmask
28 {
29  QStringList ret;
30 #if 1 //a disk with multiple partitions removed
31  char driveName[] = "A:/";
32  driveBits &= 0x3ffffff;
33  while (driveBits) {
34  if (driveBits & 0x1)
35  ret.append(QString::fromLatin1(driveName));
36  ++driveName[0];
37  driveBits >>= 1;
38  }
39  return ret;
40 #else
41  char i = 0;
42  for (; i<26; ++i) {
43  if (driveBits & 0x1)
44  break;
45  driveBits >>= 1;
46  }
47  QChar c(i + 'A');
48  return ret << QString(c) + ":";
49 #endif
50 }
51 
52 LRESULT CALLBACK dw_internal_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
53 {
54  if (message == WM_DEVICECHANGE) {
55  DEV_BROADCAST_HDR *lpdb = (DEV_BROADCAST_HDR *)lParam;
56  qDebug("Device type address: %#x", lpdb);
57  if (lpdb) {
58  if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) {
59  qDebug("DBT_DEVTYP_VOLUME");
60  } else if (lpdb->dbch_devicetype == DBT_DEVTYP_PORT) {
61  qDebug("DBT_DEVTYP_PORT");
62  } else if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
63  qDebug("DBT_DEVTYP_DEVICEINTERFACE");
64  } else if (lpdb->dbch_devicetype == DBT_DEVTYP_OEM) {
65  qDebug("DBT_DEVTYP_OEM");
66  } else {
67  qDebug("Unknow device type");
68  }
69  }
70 
71  switch (wParam) {
72  case DBT_DEVNODES_CHANGED:
73  qDebug("DBT_DEVNODES_CHANGED message received, no extended info.");
74  break;
75  case DBT_QUERYCHANGECONFIG:
76  qDebug("DBT_QUERYCHANGECONFIG message received, no extended info.");
77  break;
78  case DBT_CONFIGCHANGED:
79  qDebug("DBT_CONFIGCHANGED message received, no extended info.");
80  break;
81  case DBT_CONFIGCHANGECANCELED:
82  qDebug("DBT_CONFIGCHANGECANCELED message received, no extended info.");
83  break;
84 
85  case DBT_DEVICEARRIVAL:
86  case DBT_DEVICEQUERYREMOVE:
87  case DBT_DEVICEQUERYREMOVEFAILED:
88  case DBT_DEVICEREMOVEPENDING:
89  case DBT_DEVICEREMOVECOMPLETE:
90  if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) {
91  DEV_BROADCAST_VOLUME *db_volume = (DEV_BROADCAST_VOLUME *)lpdb;
92  QStringList drives = drivesFromMask(db_volume->dbcv_unitmask);
93 #ifdef GWLP_USERDATA
94  QDeviceWatcherPrivate *watcher = (QDeviceWatcherPrivate *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
95 #else
96  QDeviceWatcherPrivate *watcher = (QDeviceWatcherPrivate *)GetWindowLong(hwnd, GWL_USERDATA);
97 #endif
98  QList<QDeviceChangeEvent *> events;
99  QString action_str("add");
101  if (wParam == DBT_DEVICEARRIVAL) {
102  } else if (wParam == DBT_DEVICEQUERYREMOVE) {
103  } else if (wParam == DBT_DEVICEQUERYREMOVEFAILED) {
104  } else if (wParam == DBT_DEVICEREMOVEPENDING) {
105  } else if (wParam == DBT_DEVICEREMOVECOMPLETE) {
106  action_str = "remove";
108  }
109  foreach (const QString &drive, drives) {
110  if (db_volume->dbcv_flags & DBTF_MEDIA)
111  qDebug("Drive %c: Media has been removed.", drive.at(0).toLatin1());
112  else if (db_volume->dbcv_flags & DBTF_NET)
113  qDebug("Drive %c: Network share has been removed.", drive.at(0).toLatin1());
114  else
115  qDebug("Drive %c: Device has been removed.", drive.at(0).toLatin1());
116  watcher->emitDeviceAction(drive, action_str);
117  if (!watcher->event_receivers.isEmpty())
118  events.append(new QDeviceChangeEvent(action, drive));
119  }
120  if (!events.isEmpty() && !watcher->event_receivers.isEmpty()) {
121  for(QObject *obj : qAsConst(watcher->event_receivers)) {
122  for(QDeviceChangeEvent *event : qAsConst(events)) {
123  QCoreApplication::postEvent(obj, event, Qt::HighEventPriority);
124  }
125  }
126  }
127  } else if (lpdb->dbch_devicetype == DBT_DEVTYP_PORT) {
128  qDebug("DBT_DEVTYP_PORT");
129  } else if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
130  //RegisterDeviceNotification()
131  qDebug("DBT_DEVTYP_DEVICEINTERFACE");
132  } else if (lpdb->dbch_devicetype == DBT_DEVTYP_OEM) {
133  qDebug("DBT_DEVTYP_OEM");
134  } else if (lpdb->dbch_devicetype == DBT_DEVTYP_HANDLE) {
135  qDebug("DBT_DEVTYP_HANDLE");
136  }
137  break;
138  case DBT_DEVICETYPESPECIFIC:
139  qDebug("DBT_DEVICETYPESPECIFIC message received, may contain an extended info.");
140  break;
141  case DBT_CUSTOMEVENT:
142  qDebug("DBT_CUSTOMEVENT message received, contains an extended info.");
143  break;
144  case DBT_USERDEFINED:
145  qDebug("WM_DEVICECHANGE user defined message received, can not handle.");
146  break;
147  default:
148  qWarning("WM_DEVICECHANGE message received, unhandled value %d.", wParam);
149  break;
150  }
151  }
152 
153  return DefWindowProc(hwnd, message, wParam, lParam);
154 }
155 
156 static QString className()
157 {
158  return QLatin1String("QDeviceWatcherPrivateWin32_Internal_Widget") + QString::number(quintptr(dw_internal_proc));
159 }
160 
161 static HWND dw_create_internal_window(const void* userData)
162 {
163  QString className = ::className();
164  HINSTANCE hi = GetModuleHandle(nullptr);
165 
166  WNDCLASSW wc;
167  wc.style = 0;
168  wc.lpfnWndProc = dw_internal_proc;
169  wc.cbClsExtra = 0;
170  wc.cbWndExtra = 0;
171  wc.hInstance = hi;
172  wc.hIcon = 0;
173  wc.hCursor = 0;
174  wc.hbrBackground = 0;
175  wc.lpszMenuName = nullptr;
176  wc.lpszClassName = TTKReinterpretCast(const wchar_t *, className.utf16());
177  RegisterClassW(&wc);
178 
179  HWND hwnd = CreateWindowW(wc.lpszClassName, // classname
180  wc.lpszClassName, // window name
181  0, // style
182  0,
183  0,
184  0,
185  0, // geometry
186  0, // parent
187  0, // menu handle
188  hi, // application
189  0); // windows creation data.
190  if (!hwnd) {
191  qWarning("QDeviceWatcherPrivate: Failed to create internal window: %d", TTKStaticCast(int, GetLastError()));
192 #if CONFIG_NOTIFICATION
193  } else {
194  DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
195  ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
196  NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
197  NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
198  NotificationFilter.dbcc_classguid = InterfaceClassGuid;
199  //3rd param with DEVICE_NOTIFY_ALL_INTERFACE_CLASSES and dbcc_classguid will be ignored
200  //http://msdn.microsoft.com/en-us/library/windows/desktop/aa363431(v=vs.85).aspx
201  hDevNotify = RegisterDeviceNotification(hwnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
202  if (!hDevNotify) {
203  qDebug("");
204  }
205  }
206 #else
207  } else if (userData) {
208 #ifdef GWLP_USERDATA
209  SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)userData);
210 #else
211  SetWindowLongW(hwnd, GWL_USERDATA, (LONG)userData);
212 #endif
213  }
214 #endif //CONFIG_NOTIFICATION
215  return hwnd;
216 }
217 
218 static void dw_destroy_internal_window(HWND hwnd)
219 {
220  if (hwnd)
221  DestroyWindow(hwnd);
222 
223 #if CONFIG_NOTIFICATION
224  UnregisterDeviceNotification(hDevNotify);
225 #endif
226  UnregisterClassW(TTKReinterpretCast(const wchar_t *, className().utf16()), GetModuleHandle(nullptr));
227 }
228 
229 
231 {
232  stop();
233 }
234 
236 {
237  if (!initialize())
238  return false;
239  hwnd = dw_create_internal_window(this);
240 
241  if (!hwnd) {
242  dw_destroy_internal_window(hwnd);
243  }
244  return hwnd;
245 }
246 
248 {
249  dw_destroy_internal_window(hwnd);
250  return true;
251 }
252 
254 {
255  return true;
256 }
257 
259 {
260 }
261 
262 #endif //Q_OS_WIN32
#define TTKStaticCast(x, y)
Definition: ttkglobal.h:231
static QString message(const TTK::Attribute attr)
#define qAsConst
Definition: ttkqtglobal.h:57
The class of the device watcher event.
void emitDeviceAction(const QString &dev, const QString &action)
The class of the device watcher private.
#define TTKReinterpretCast(x, y)
Definition: ttkglobal.h:225