TTKMusicPlayer  3.7.0.0
TTKMusicPlayer imitates Kugou UI, the music player uses of qmmp core library based on Qt for windows and linux
musicdeviceinfomodule.cpp
Go to the documentation of this file.
2 #include "ttksemaphoreloop.h"
3 
4 #ifdef Q_OS_WIN
5 # include <QDir>
6 # include <QFileInfoList>
7 # include <qt_windows.h>
8 static constexpr int BUFFER_SIZE = 255;
9 #endif
10 
12  : QObject(parent)
13 {
14 #ifdef Q_OS_UNIX
15  m_process = new QProcess(this);
16  connect(m_process, SIGNAL(readyRead()), this, SLOT(handleReadyRead()));
17 #endif
18 }
19 
21 {
22 #ifdef Q_OS_UNIX
23  delete m_process;
24 #endif
25 }
26 
27 bool MusicDeviceInfoModule::disksProperty(const QString &drive) const
28 {
29 #ifdef Q_OS_WIN
30  STORAGE_PROPERTY_QUERY query;
31  query.PropertyId = StorageDeviceProperty;
32  query.QueryType = PropertyStandardQuery;
33 
34  QString name = drive;
35  name = "\\\\.\\" + name.left(name.length() - 1);
36 
37  HANDLE hDevice = CreateFileW(
38  name.toStdWString().c_str(),
39  GENERIC_READ | GENERIC_WRITE,
40  FILE_SHARE_READ | FILE_SHARE_WRITE,
41  nullptr,
42  OPEN_EXISTING,
43  0,
44  nullptr);
45 
46  if(hDevice == INVALID_HANDLE_VALUE)
47  {
48  return false;
49  }
50 
51  STORAGE_DESCRIPTOR_HEADER *pHeader = (STORAGE_DESCRIPTOR_HEADER *)malloc(sizeof(STORAGE_DESCRIPTOR_HEADER));
52  if(!pHeader)
53  {
54  return false;
55  }
56 
57  DWORD bytes = 0;
58  BOOL bResult = DeviceIoControl(
59  hDevice,
60  IOCTL_STORAGE_QUERY_PROPERTY,
61  &query,
62  sizeof(query),
63  pHeader,
64  sizeof(STORAGE_DESCRIPTOR_HEADER),
65  &bytes,
66  nullptr);
67 
68  if(!bResult)
69  {
70  free(pHeader);
71  CloseHandle(hDevice);
72  return false;
73  }
74 
75  PSTORAGE_DEVICE_DESCRIPTOR pDev = (STORAGE_DEVICE_DESCRIPTOR *)malloc(pHeader->Size);
76  DeviceIoControl(
77  hDevice,
78  IOCTL_STORAGE_QUERY_PROPERTY,
79  &query,
80  sizeof(query),
81  pDev,
82  pHeader->Size,
83  &bytes,
84  nullptr);
85 
86  free(pHeader);
87  CloseHandle(hDevice);
88 
89  if(pDev->BusType == BusTypeUsb)
90  {
91  free(pDev);
92  return true;
93  }
94 
95  free(pDev);
96  return false;
97 #else
98  Q_UNUSED(drive);
99  return false;
100 #endif
101 }
102 
103 MusicDeviceInfoItemList MusicDeviceInfoModule::removableDrive()
104 {
105  m_items.clear();
106 #ifdef Q_OS_WIN
107  for(const QFileInfo &fin : QDir::drives())
108  {
109  const QString &path = fin.absoluteDir().absolutePath();
110  const int type = GetDriveTypeW(path.toStdWString().c_str());
111  if(type == DRIVE_REMOVABLE)
112  {
113 
114  }
115  else if(type == DRIVE_FIXED)
116  {
117  if(!disksProperty(path))
118  {
119  continue;
120  }
121  }
122  else
123  {
124  continue;
125  }
126 
127  ULARGE_INTEGER freeAvailable;
128  ULARGE_INTEGER totalNumberOfBytes;
129  ULARGE_INTEGER totalNumberOfFreeBytes;
130 
131  if(GetDiskFreeSpaceExW(path.toStdWString().c_str(), &freeAvailable, &totalNumberOfBytes, &totalNumberOfFreeBytes))
132  {
133  const qint64 available = freeAvailable.QuadPart / TTK_SN_GB2B;
134  const qint64 total = totalNumberOfBytes.QuadPart / TTK_SN_GB2B;
135 
136  MusicDeviceInfoItem item;
137  item.m_path = path;
138  item.m_usedBytes = total - available;
139  item.m_totalBytes = total;
140 
141  if(item.m_usedBytes < 0)
142  {
143  item.m_usedBytes = 0;
144  }
145  else if(item.m_usedBytes >= item.m_totalBytes)
146  {
147  item.m_usedBytes = item.m_totalBytes;
148  }
149 
150  DWORD serialNumber = 0;
151  DWORD maxLength = 0;
152  DWORD fileSysFlags = 0;
153 
154  WCHAR dirveName[BUFFER_SIZE];
155  WCHAR fileSysTypeName[BUFFER_SIZE];
156 
157  if(GetVolumeInformationW(
158  item.m_path.toStdWString().c_str(),
159  dirveName,
160  BUFFER_SIZE,
161  &serialNumber,
162  &maxLength,
163  &fileSysFlags,
164  fileSysTypeName,
165  BUFFER_SIZE))
166  {
167  item.m_name = QString::fromStdWString(dirveName);
168  }
169  m_items << item;
170  }
171  }
172 #else
173  TTKSemaphoreLoop loop;
174  connect(m_process, SIGNAL(finished(int)), &loop, SLOT(quit()));
175  QtProcessVoidConnect(m_process, &loop, quit, TTK_SLOT);
176  m_process->close();
177  m_process->start("df", {"-h"});
178  loop.exec();
179 #endif
180  return m_items;
181 }
182 
183 #ifdef Q_OS_UNIX
184 static int driveSizeToNumber(QString &v)
185 {
186  if(v.endsWith("G"))
187  {
188  v.remove("G");
189  return v.toDouble();
190  }
191  else if(v.endsWith("M"))
192  {
193  v.remove("M");
194  return 1;
195  }
196  return 0;
197 }
198 
199 void MusicDeviceInfoModule::handleReadyRead()
200 {
201  while(!m_process->atEnd())
202  {
203  const QString &result = QString::fromLocal8Bit(m_process->readLine());
204  if(result.startsWith("/dev/sd"))
205  {
206  QString dev, use, total, path;
207  int index = 0;
208 
209  const QStringList &list = result.split(" ");
210  for(int i = 0; i < list.count(); ++i)
211  {
212  const QString &data = list.at(i).trimmed();
213  if(data.isEmpty())
214  {
215  continue;
216  }
217 
218  index++;
219  if(index == 1)
220  {
221  dev = data;
222  }
223  else if(index == 2)
224  {
225  total = data;
226  }
227  else if(index == 3)
228  {
229  use = data;
230  }
231  else if(index == 6)
232  {
233  path = data;
234  }
235  }
236 
237  if(path.startsWith("/media/"))
238  {
239  MusicDeviceInfoItem item;
240  item.m_name = dev;
241  item.m_path = path;
242  item.m_usedBytes = driveSizeToNumber(use);
243  item.m_totalBytes = driveSizeToNumber(total);
244 
245  if(item.m_usedBytes < 0)
246  {
247  item.m_usedBytes = 0;
248  }
249  else if(item.m_usedBytes >= item.m_totalBytes)
250  {
251  item.m_usedBytes = item.m_totalBytes;
252  }
253  m_items << item;
254  }
255  }
256  }
257 }
258 #endif
MusicDeviceInfoItemList m_items
int exec(ProcessEventsFlags flags=AllEvents)
#define INVALID_HANDLE_VALUE
Definition: iowin32.c:21
#define QtProcessVoidConnect(p, q, f, s)
Process error void connect.
Definition: ttkqtcompat.h:94
The class of the system device info item.
#define TTK_SN_GB2B
Definition: ttkglobal.h:320
const char * name
Definition: http_parser.c:458
bool disksProperty(const QString &drive) const
MusicDeviceInfoItemList removableDrive()
#define TTK_SLOT
Definition: ttkqtglobal.h:165
MusicDeviceInfoModule(QObject *parent=nullptr)
void free(voidpf ptr)
voidp malloc(uInt size)
The class of the semaphore event loop.