TTKMusicPlayer  3.7.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 <QtCore/QStringList>
7 #include <QtCore/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 Q_CORE_EXPORT HINSTANCE qWinAppInst();
28 
29 static QStringList drivesFromMask(quint32 driveBits) //driveBits ->unitmask
30 {
31  QStringList ret;
32 #if 1 //a disk with multiple partitions removed
33  char driveName[] = "A:/";
34  driveBits &= 0x3ffffff;
35  while (driveBits) {
36  if (driveBits & 0x1)
37  ret.append(QString::fromLatin1(driveName));
38  ++driveName[0];
39  driveBits >>= 1;
40  }
41  return ret;
42 #else
43  char i = 0;
44  for (; i<26; ++i) {
45  if (driveBits & 0x1)
46  break;
47  driveBits >>= 1;
48  }
49  QChar c(i + 'A');
50  return ret << QString(c) + ":";
51 #endif
52 }
53 
54 LRESULT CALLBACK dw_internal_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
55 {
56  if (message == WM_DEVICECHANGE) {
57  DEV_BROADCAST_HDR *lpdb = (DEV_BROADCAST_HDR *)lParam;
58  qDebug("Device type address: %#x", lpdb);
59  if (lpdb) {
60  if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) {
61  qDebug("DBT_DEVTYP_VOLUME");
62  } else if (lpdb->dbch_devicetype == DBT_DEVTYP_PORT) {
63  qDebug("DBT_DEVTYP_PORT");
64  } else if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
65  qDebug("DBT_DEVTYP_DEVICEINTERFACE");
66  } else if (lpdb->dbch_devicetype == DBT_DEVTYP_OEM) {
67  qDebug("DBT_DEVTYP_OEM");
68  } else {
69  qDebug("Unknow device type");
70  }
71  }
72 
73  switch (wParam) {
74  case DBT_DEVNODES_CHANGED:
75  qDebug("DBT_DEVNODES_CHANGED message received, no extended info.");
76  break;
77  case DBT_QUERYCHANGECONFIG:
78  qDebug("DBT_QUERYCHANGECONFIG message received, no extended info.");
79  break;
80  case DBT_CONFIGCHANGED:
81  qDebug("DBT_CONFIGCHANGED message received, no extended info.");
82  break;
83  case DBT_CONFIGCHANGECANCELED:
84  qDebug("DBT_CONFIGCHANGECANCELED message received, no extended info.");
85  break;
86 
87  case DBT_DEVICEARRIVAL:
88  case DBT_DEVICEQUERYREMOVE:
89  case DBT_DEVICEQUERYREMOVEFAILED:
90  case DBT_DEVICEREMOVEPENDING:
91  case DBT_DEVICEREMOVECOMPLETE:
92  if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) {
93  DEV_BROADCAST_VOLUME *db_volume = (DEV_BROADCAST_VOLUME *)lpdb;
94  QStringList drives = drivesFromMask(db_volume->dbcv_unitmask);
95 #ifdef GWLP_USERDATA
96  QDeviceWatcherPrivate *watcher = (QDeviceWatcherPrivate *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
97 #else
98  QDeviceWatcherPrivate *watcher = (QDeviceWatcherPrivate *)GetWindowLong(hwnd, GWL_USERDATA);
99 #endif
100  QList<QDeviceChangeEvent *> events;
101  QString action_str("add");
103  if (wParam == DBT_DEVICEARRIVAL) {
104  } else if (wParam == DBT_DEVICEQUERYREMOVE) {
105  } else if (wParam == DBT_DEVICEQUERYREMOVEFAILED) {
106  } else if (wParam == DBT_DEVICEREMOVEPENDING) {
107  } else if (wParam == DBT_DEVICEREMOVECOMPLETE) {
108  action_str = "remove";
110  }
111  foreach (const QString &drive, drives) {
112  if (db_volume->dbcv_flags & DBTF_MEDIA)
113  qDebug("Drive %c: Media has been removed.", drive.at(0).toLatin1());
114  else if (db_volume->dbcv_flags & DBTF_NET)
115  qDebug("Drive %c: Network share has been removed.", drive.at(0).toLatin1());
116  else
117  qDebug("Drive %c: Device has been removed.", drive.at(0).toLatin1());
118  watcher->emitDeviceAction(drive, action_str);
119  if (!watcher->event_receivers.isEmpty())
120  events.append(new QDeviceChangeEvent(action, drive));
121  }
122  if (!events.isEmpty() && !watcher->event_receivers.isEmpty()) {
123  for(QObject *obj : qAsConst(watcher->event_receivers)) {
124  for(QDeviceChangeEvent *event : qAsConst(events)) {
125  QCoreApplication::postEvent(obj, event, Qt::HighEventPriority);
126  }
127  }
128  }
129  } else if (lpdb->dbch_devicetype == DBT_DEVTYP_PORT) {
130  qDebug("DBT_DEVTYP_PORT");
131  } else if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
132  //RegisterDeviceNotification()
133  qDebug("DBT_DEVTYP_DEVICEINTERFACE");
134  } else if (lpdb->dbch_devicetype == DBT_DEVTYP_OEM) {
135  qDebug("DBT_DEVTYP_OEM");
136  } else if (lpdb->dbch_devicetype == DBT_DEVTYP_HANDLE) {
137  qDebug("DBT_DEVTYP_HANDLE");
138  }
139  break;
140  case DBT_DEVICETYPESPECIFIC:
141  qDebug("DBT_DEVICETYPESPECIFIC message received, may contain an extended info.");
142  break;
143  case DBT_CUSTOMEVENT:
144  qDebug("DBT_CUSTOMEVENT message received, contains an extended info.");
145  break;
146  case DBT_USERDEFINED:
147  qDebug("WM_DEVICECHANGE user defined message received, can not handle.");
148  break;
149  default:
150  qWarning("WM_DEVICECHANGE message received, unhandled value %d.", wParam);
151  break;
152  }
153  }
154 
155  return DefWindowProc(hwnd, message, wParam, lParam);
156 }
157 
158 static QString className()
159 {
160  return QLatin1String("QDeviceWatcherPrivateWin32_Internal_Widget") + QString::number(quintptr(dw_internal_proc));
161 }
162 
163 static HWND dw_create_internal_window(const void* userData)
164 {
165  QString className = ::className();
166  HINSTANCE hi = qWinAppInst();
167 
168  WNDCLASSW wc;
169  wc.style = 0;
170  wc.lpfnWndProc = dw_internal_proc;
171  wc.cbClsExtra = 0;
172  wc.cbWndExtra = 0;
173  wc.hInstance = hi;
174  wc.hIcon = 0;
175  wc.hCursor = 0;
176  wc.hbrBackground = 0;
177  wc.lpszMenuName = nullptr;
178  wc.lpszClassName = TTKReinterpretCast(const wchar_t *, className.utf16());
179  RegisterClassW(&wc);
180 
181  HWND hwnd = CreateWindowW(wc.lpszClassName, // classname
182  wc.lpszClassName, // window name
183  0, // style
184  0,
185  0,
186  0,
187  0, // geometry
188  0, // parent
189  0, // menu handle
190  hi, // application
191  0); // windows creation data.
192  if (!hwnd) {
193  qWarning("QDeviceWatcherPrivate: Failed to create internal window: %d", (int)GetLastError());
194 #if CONFIG_NOTIFICATION
195  } else {
196  DEV_BROADCAST_DEVICEINTERFACE NotificationFilter ;
197  ZeroMemory(&NotificationFilter, sizeof(NotificationFilter)) ;
198  NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
199  NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
200  NotificationFilter.dbcc_classguid = InterfaceClassGuid;
201  //3rd param with DEVICE_NOTIFY_ALL_INTERFACE_CLASSES and dbcc_classguid will be ignored
202  //http://msdn.microsoft.com/en-us/library/windows/desktop/aa363431(v=vs.85).aspx
203  hDevNotify = RegisterDeviceNotification(hwnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
204  if (!hDevNotify) {
205  qDebug("");
206  }
207  }
208 #else
209  } else if (userData) {
210 #ifdef GWLP_USERDATA
211  SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)userData);
212 #else
213  SetWindowLongW(hwnd, GWL_USERDATA, (LONG)userData);
214 #endif
215  }
216 #endif //CONFIG_NOTIFICATION
217  return hwnd;
218 }
219 
220 static void dw_destroy_internal_window(HWND hwnd)
221 {
222  if (hwnd)
223  DestroyWindow(hwnd);
224 
225 #if CONFIG_NOTIFICATION
226  UnregisterDeviceNotification(hDevNotify);
227 #endif
228  UnregisterClassW(TTKReinterpretCast(const wchar_t *, className().utf16()), qWinAppInst());
229 }
230 
231 
232 
234 {
235  stop();
236 }
237 
239 {
240  initialize();
241  hwnd = dw_create_internal_window(this);
242 
243  if (!hwnd) {
244  dw_destroy_internal_window(hwnd);
245  }
246  return hwnd;
247 }
248 
250 {
251  dw_destroy_internal_window(hwnd);
252  return true;
253 }
254 
256 {
257  return true;
258 }
259 
261 {
262 }
263 
264 #endif //Q_OS_WIN32
#define qAsConst
Definition: ttkqtglobal.h:53
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:153