annotate system/System.cpp @ 661:a4faa1840384

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