Chris@222
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@222
|
2
|
Chris@222
|
3 /*
|
Chris@222
|
4 Sonic Visualiser
|
Chris@222
|
5 An audio file viewer and annotation editor.
|
Chris@222
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@222
|
7 This file copyright 2006 Chris Cannam and QMUL.
|
Chris@222
|
8
|
Chris@222
|
9 This program is free software; you can redistribute it and/or
|
Chris@222
|
10 modify it under the terms of the GNU General Public License as
|
Chris@222
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@222
|
12 License, or (at your option) any later version. See the file
|
Chris@222
|
13 COPYING included with this distribution for more information.
|
Chris@222
|
14 */
|
Chris@222
|
15
|
Chris@222
|
16 #include "System.h"
|
Chris@222
|
17
|
Chris@222
|
18 #include <QStringList>
|
Chris@222
|
19 #include <QString>
|
Chris@222
|
20
|
Chris@222
|
21 #include <stdint.h>
|
Chris@222
|
22
|
Chris@222
|
23 #ifndef _WIN32
|
Chris@222
|
24 #include <signal.h>
|
Chris@222
|
25 #include <sys/statvfs.h>
|
Chris@222
|
26 #include <windows.h>
|
Chris@222
|
27 #endif
|
Chris@222
|
28
|
Chris@222
|
29 #ifdef __APPLE__
|
Chris@222
|
30 #include <sys/param.h>
|
Chris@222
|
31 #include <sys/sysctl.h>
|
Chris@222
|
32 #endif
|
Chris@222
|
33
|
Chris@222
|
34 #include <iostream>
|
Chris@222
|
35
|
Chris@222
|
36 #ifdef _WIN32
|
Chris@222
|
37
|
Chris@222
|
38 extern "C" {
|
Chris@222
|
39
|
Chris@222
|
40 void usleep(unsigned long usec)
|
Chris@222
|
41 {
|
Chris@222
|
42 ::Sleep(usec / 1000);
|
Chris@222
|
43 }
|
Chris@222
|
44
|
Chris@222
|
45 void gettimeofday(struct timeval *tv, void *tz)
|
Chris@222
|
46 {
|
Chris@222
|
47 union {
|
Chris@222
|
48 long long ns100;
|
Chris@222
|
49 FILETIME ft;
|
Chris@222
|
50 } now;
|
Chris@222
|
51
|
Chris@222
|
52 ::GetSystemTimeAsFileTime(&now.ft);
|
Chris@222
|
53 tv->tv_usec = (long)((now.ns100 / 10LL) % 1000000LL);
|
Chris@222
|
54 tv->tv_sec = (long)((now.ns100 - 116444736000000000LL) / 10000000LL);
|
Chris@222
|
55 }
|
Chris@222
|
56
|
Chris@222
|
57 }
|
Chris@222
|
58
|
Chris@222
|
59 #endif
|
Chris@222
|
60
|
Chris@222
|
61 ProcessStatus
|
Chris@222
|
62 GetProcessStatus(int pid)
|
Chris@222
|
63 {
|
Chris@222
|
64 #ifdef _WIN32
|
Chris@222
|
65 HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
|
Chris@222
|
66 if (!handle) {
|
Chris@222
|
67 return ProcessNotRunning;
|
Chris@222
|
68 } else {
|
Chris@222
|
69 CloseHandle(handle);
|
Chris@222
|
70 return ProcessRunning;
|
Chris@222
|
71 }
|
Chris@222
|
72 #else
|
Chris@222
|
73 if (kill(getpid(), 0) == 0) {
|
Chris@222
|
74 if (kill(pid, 0) == 0) {
|
Chris@222
|
75 return ProcessRunning;
|
Chris@222
|
76 } else {
|
Chris@222
|
77 return ProcessNotRunning;
|
Chris@222
|
78 }
|
Chris@222
|
79 } else {
|
Chris@222
|
80 return UnknownProcessStatus;
|
Chris@222
|
81 }
|
Chris@222
|
82 #endif
|
Chris@222
|
83 }
|
Chris@222
|
84
|
Chris@222
|
85 #ifdef _WIN32
|
Chris@222
|
86 /* MEMORYSTATUSEX is missing from older Windows headers, so define a
|
Chris@222
|
87 local replacement. This trick from MinGW source code. Ugh */
|
Chris@222
|
88 typedef struct
|
Chris@222
|
89 {
|
Chris@222
|
90 DWORD dwLength;
|
Chris@222
|
91 DWORD dwMemoryLoad;
|
Chris@222
|
92 DWORDLONG ullTotalPhys;
|
Chris@222
|
93 DWORDLONG ullAvailPhys;
|
Chris@222
|
94 DWORDLONG ullTotalPageFile;
|
Chris@222
|
95 DWORDLONG ullAvailPageFile;
|
Chris@222
|
96 DWORDLONG ullTotalVirtual;
|
Chris@222
|
97 DWORDLONG ullAvailVirtual;
|
Chris@222
|
98 DWORDLONG ullAvailExtendedVirtual;
|
Chris@222
|
99 } lMEMORYSTATUSEX;
|
Chris@222
|
100 typedef WINBOOL (WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*);
|
Chris@222
|
101 #endif
|
Chris@222
|
102
|
Chris@222
|
103 void
|
Chris@222
|
104 GetRealMemoryMBAvailable(int &available, int &total)
|
Chris@222
|
105 {
|
Chris@222
|
106 available = -1;
|
Chris@222
|
107 total = -1;
|
Chris@222
|
108
|
Chris@222
|
109 #ifdef _WIN32
|
Chris@222
|
110
|
Chris@222
|
111 static bool checked = false;
|
Chris@222
|
112 static bool exFound = false;
|
Chris@222
|
113 static PFN_MS_EX ex;
|
Chris@222
|
114
|
Chris@222
|
115 if (!checked) {
|
Chris@222
|
116
|
Chris@222
|
117 HMODULE h = GetModuleHandleA("kernel32.dll");
|
Chris@222
|
118
|
Chris@222
|
119 if (h) {
|
Chris@222
|
120 if ((ex = (PFN_MS_EX)GetProcAddress(h, "GlobalMemoryStatusEx"))) {
|
Chris@222
|
121 exFound = true;
|
Chris@222
|
122 }
|
Chris@222
|
123 }
|
Chris@222
|
124
|
Chris@222
|
125 checked = true;
|
Chris@222
|
126 }
|
Chris@222
|
127
|
Chris@222
|
128 DWORDLONG wavail = 0;
|
Chris@222
|
129 DWORDLONG wtotal = 0;
|
Chris@222
|
130
|
Chris@222
|
131 if (exFound) {
|
Chris@222
|
132
|
Chris@222
|
133 lMEMORYSTATUSEX lms;
|
Chris@222
|
134 lms.dwLength = sizeof(lms);
|
Chris@222
|
135 if (!ex(&lms)) {
|
Chris@222
|
136 std::cerr << "WARNING: GlobalMemoryStatusEx failed: error code "
|
Chris@222
|
137 << GetLastError() << std::endl;
|
Chris@222
|
138 return;
|
Chris@222
|
139 }
|
Chris@222
|
140 wavail = lms.ullAvailPhys;
|
Chris@222
|
141 wtotal = lms.ullTotalPhys;
|
Chris@222
|
142
|
Chris@222
|
143 } else {
|
Chris@222
|
144
|
Chris@222
|
145 /* Fall back to GlobalMemoryStatus which is always available.
|
Chris@222
|
146 but returns wrong results for physical memory > 4GB */
|
Chris@222
|
147
|
Chris@222
|
148 MEMORYSTATUS ms;
|
Chris@222
|
149 GlobalMemoryStatus(&ms);
|
Chris@222
|
150 wavail = ms.dwAvailPhys;
|
Chris@222
|
151 wtotal = ms.dwTotalPhys;
|
Chris@222
|
152 }
|
Chris@222
|
153
|
Chris@222
|
154 DWORDLONG size = wavail / 1048576;
|
Chris@222
|
155 if (size > INT_MAX) size = INT_MAX;
|
Chris@222
|
156 available = int(size);
|
Chris@222
|
157
|
Chris@222
|
158 size = wtotal / 1048576;
|
Chris@222
|
159 if (size > INT_MAX) size = INT_MAX;
|
Chris@222
|
160 total = int(size);
|
Chris@222
|
161
|
Chris@222
|
162 return;
|
Chris@222
|
163
|
Chris@222
|
164 #else
|
Chris@222
|
165 #ifdef __APPLE__
|
Chris@222
|
166
|
Chris@222
|
167 unsigned int val;
|
Chris@222
|
168 int mib[2];
|
Chris@222
|
169 size_t size_sys;
|
Chris@222
|
170
|
Chris@222
|
171 mib[0] = CTL_HW;
|
Chris@222
|
172
|
Chris@222
|
173 mib[1] = HW_PHYSMEM;
|
Chris@222
|
174 size_sys = sizeof(val);
|
Chris@222
|
175 sysctl(mib, 2, &val, &size_sys, NULL, 0);
|
Chris@222
|
176 if (val) total = val / 1048576;
|
Chris@222
|
177
|
Chris@222
|
178 mib[1] = HW_USERMEM;
|
Chris@222
|
179 size_sys = sizeof(val);
|
Chris@222
|
180 sysctl(mib, 2, &val, &size_sys, NULL, 0);
|
Chris@222
|
181 if (val) available = val / 1048576;
|
Chris@222
|
182
|
Chris@222
|
183 return;
|
Chris@222
|
184
|
Chris@222
|
185 #else
|
Chris@222
|
186
|
Chris@222
|
187 FILE *meminfo = fopen("/proc/meminfo", "r");
|
Chris@222
|
188 if (!meminfo) return;
|
Chris@222
|
189
|
Chris@222
|
190 char buf[256];
|
Chris@222
|
191 while (!feof(meminfo)) {
|
Chris@222
|
192 fgets(buf, 256, meminfo);
|
Chris@222
|
193 bool isMemFree = (strncmp(buf, "MemFree:", 8) == 0);
|
Chris@222
|
194 bool isMemTotal = (!isMemFree && (strncmp(buf, "MemTotal:", 9) == 0));
|
Chris@222
|
195 if (isMemFree || isMemTotal) {
|
Chris@222
|
196 QString line = QString(buf).trimmed();
|
Chris@222
|
197 QStringList elements = line.split(' ', QString::SkipEmptyParts);
|
Chris@222
|
198 QString unit = "kB";
|
Chris@222
|
199 if (elements.size() > 2) unit = elements[2];
|
Chris@222
|
200 int size = elements[1].toInt();
|
Chris@222
|
201 // std::cerr << "have size \"" << size << "\", unit \""
|
Chris@222
|
202 // << unit.toStdString() << "\"" << std::endl;
|
Chris@222
|
203 if (unit.toLower() == "gb") size = size * 1024;
|
Chris@222
|
204 else if (unit.toLower() == "mb") size = size;
|
Chris@222
|
205 else if (unit.toLower() == "kb") size = size / 1024;
|
Chris@222
|
206 else size = size / 1048576;
|
Chris@222
|
207
|
Chris@222
|
208 if (isMemFree) available = size;
|
Chris@222
|
209 else total = size;
|
Chris@222
|
210 }
|
Chris@222
|
211 if (available != -1 && total != -1) {
|
Chris@222
|
212 fclose(meminfo);
|
Chris@222
|
213 return;
|
Chris@222
|
214 }
|
Chris@222
|
215 }
|
Chris@222
|
216 fclose(meminfo);
|
Chris@222
|
217
|
Chris@222
|
218 return;
|
Chris@222
|
219
|
Chris@222
|
220 #endif
|
Chris@222
|
221 #endif
|
Chris@222
|
222 }
|
Chris@222
|
223
|
Chris@222
|
224 int
|
Chris@222
|
225 GetDiscSpaceMBAvailable(const char *path)
|
Chris@222
|
226 {
|
Chris@222
|
227 #ifdef _WIN32
|
Chris@222
|
228 ULARGE_INTEGER available, total, totalFree;
|
Chris@222
|
229 if (GetDiskFreeSpaceExA(path, &available, &total, &totalFree)) {
|
Chris@222
|
230 __int64 a = available.QuadPart;
|
Chris@222
|
231 a /= 1048576;
|
Chris@222
|
232 if (a > INT_MAX) a = INT_MAX;
|
Chris@222
|
233 return int(a);
|
Chris@222
|
234 } else {
|
Chris@222
|
235 std::cerr << "WARNING: GetDiskFreeSpaceEx failed: error code "
|
Chris@222
|
236 << GetLastError() << std::endl;
|
Chris@222
|
237 return -1;
|
Chris@222
|
238 }
|
Chris@222
|
239 #else
|
Chris@222
|
240 struct statvfs buf;
|
Chris@222
|
241 if (!statvfs(path, &buf)) {
|
Chris@222
|
242 // do the multiplies and divides in this order to reduce the
|
Chris@222
|
243 // likelihood of arithmetic overflow
|
Chris@222
|
244 std::cerr << "statvfs(" << path << ") says available: " << buf.f_bavail << ", block size: " << buf.f_bsize << std::endl;
|
Chris@222
|
245 uint64_t available = ((buf.f_bavail / 1024) * buf.f_bsize) / 1024;
|
Chris@222
|
246 if (available > INT_MAX) available = INT_MAX;
|
Chris@222
|
247 return int(available);
|
Chris@222
|
248 } else {
|
Chris@222
|
249 perror("statvfs failed");
|
Chris@222
|
250 return -1;
|
Chris@222
|
251 }
|
Chris@222
|
252 #endif
|
Chris@222
|
253 }
|
Chris@222
|
254
|
Chris@222
|
255
|
Chris@222
|
256 double mod(double x, double y) { return x - (y * floor(x / y)); }
|
Chris@222
|
257 float modf(float x, float y) { return x - (y * floorf(x / y)); }
|
Chris@222
|
258
|
Chris@222
|
259 double princarg(double a) { return mod(a + M_PI, -2 * M_PI) + M_PI; }
|
Chris@222
|
260 float princargf(float a) { return modf(a + M_PI, -2 * M_PI) + M_PI; }
|
Chris@222
|
261
|