annotate system/System.cpp @ 392:183ee2a55fc7

* More work to abstract out interactive components used in the data library, so that it does not need to depend on QtGui.
author Chris Cannam
date Fri, 14 Mar 2008 17:14:21 +0000
parents 15b47d30c085
children 65311fb86166
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@223 26 #endif
Chris@223 27
Chris@223 28 #ifdef __APPLE__
Chris@223 29 #include <sys/param.h>
Chris@223 30 #include <sys/sysctl.h>
Chris@223 31 #endif
Chris@223 32
Chris@223 33 #include <iostream>
Chris@223 34
Chris@255 35 #ifdef __APPLE__
Chris@255 36 extern "C" {
Chris@255 37 void *
Chris@255 38 rpl_realloc (void *p, size_t n)
Chris@255 39 {
Chris@255 40 p = realloc(p, n);
Chris@255 41 if (p == 0 && n == 0)
Chris@255 42 {
Chris@255 43 p = malloc(0);
Chris@255 44 }
Chris@255 45 return p;
Chris@255 46 }
Chris@255 47 }
Chris@255 48 #endif
Chris@255 49
Chris@223 50 #ifdef _WIN32
Chris@223 51
Chris@223 52 extern "C" {
Chris@223 53
Chris@223 54 void usleep(unsigned long usec)
Chris@223 55 {
Chris@223 56 ::Sleep(usec / 1000);
Chris@223 57 }
Chris@223 58
Chris@223 59 void gettimeofday(struct timeval *tv, void *tz)
Chris@223 60 {
Chris@223 61 union {
Chris@223 62 long long ns100;
Chris@223 63 FILETIME ft;
Chris@223 64 } now;
Chris@223 65
Chris@223 66 ::GetSystemTimeAsFileTime(&now.ft);
Chris@223 67 tv->tv_usec = (long)((now.ns100 / 10LL) % 1000000LL);
Chris@223 68 tv->tv_sec = (long)((now.ns100 - 116444736000000000LL) / 10000000LL);
Chris@223 69 }
Chris@223 70
Chris@223 71 }
Chris@223 72
Chris@223 73 #endif
Chris@223 74
Chris@223 75 ProcessStatus
Chris@223 76 GetProcessStatus(int pid)
Chris@223 77 {
Chris@223 78 #ifdef _WIN32
Chris@223 79 HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
Chris@223 80 if (!handle) {
Chris@223 81 return ProcessNotRunning;
Chris@223 82 } else {
Chris@223 83 CloseHandle(handle);
Chris@223 84 return ProcessRunning;
Chris@223 85 }
Chris@223 86 #else
Chris@223 87 if (kill(getpid(), 0) == 0) {
Chris@223 88 if (kill(pid, 0) == 0) {
Chris@223 89 return ProcessRunning;
Chris@223 90 } else {
Chris@223 91 return ProcessNotRunning;
Chris@223 92 }
Chris@223 93 } else {
Chris@223 94 return UnknownProcessStatus;
Chris@223 95 }
Chris@223 96 #endif
Chris@223 97 }
Chris@223 98
Chris@223 99 #ifdef _WIN32
Chris@223 100 /* MEMORYSTATUSEX is missing from older Windows headers, so define a
Chris@223 101 local replacement. This trick from MinGW source code. Ugh */
Chris@223 102 typedef struct
Chris@223 103 {
Chris@223 104 DWORD dwLength;
Chris@223 105 DWORD dwMemoryLoad;
Chris@223 106 DWORDLONG ullTotalPhys;
Chris@223 107 DWORDLONG ullAvailPhys;
Chris@223 108 DWORDLONG ullTotalPageFile;
Chris@223 109 DWORDLONG ullAvailPageFile;
Chris@223 110 DWORDLONG ullTotalVirtual;
Chris@223 111 DWORDLONG ullAvailVirtual;
Chris@223 112 DWORDLONG ullAvailExtendedVirtual;
Chris@223 113 } lMEMORYSTATUSEX;
Chris@223 114 typedef WINBOOL (WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*);
Chris@223 115 #endif
Chris@223 116
Chris@223 117 void
Chris@223 118 GetRealMemoryMBAvailable(int &available, int &total)
Chris@223 119 {
Chris@223 120 available = -1;
Chris@223 121 total = -1;
Chris@223 122
Chris@223 123 #ifdef _WIN32
Chris@223 124
Chris@223 125 static bool checked = false;
Chris@223 126 static bool exFound = false;
Chris@223 127 static PFN_MS_EX ex;
Chris@223 128
Chris@223 129 if (!checked) {
Chris@223 130
Chris@223 131 HMODULE h = GetModuleHandleA("kernel32.dll");
Chris@223 132
Chris@223 133 if (h) {
Chris@223 134 if ((ex = (PFN_MS_EX)GetProcAddress(h, "GlobalMemoryStatusEx"))) {
Chris@223 135 exFound = true;
Chris@223 136 }
Chris@223 137 }
Chris@223 138
Chris@223 139 checked = true;
Chris@223 140 }
Chris@223 141
Chris@223 142 DWORDLONG wavail = 0;
Chris@223 143 DWORDLONG wtotal = 0;
Chris@223 144
Chris@223 145 if (exFound) {
Chris@223 146
Chris@223 147 lMEMORYSTATUSEX lms;
Chris@223 148 lms.dwLength = sizeof(lms);
Chris@223 149 if (!ex(&lms)) {
Chris@223 150 std::cerr << "WARNING: GlobalMemoryStatusEx failed: error code "
Chris@223 151 << GetLastError() << std::endl;
Chris@223 152 return;
Chris@223 153 }
Chris@223 154 wavail = lms.ullAvailPhys;
Chris@223 155 wtotal = lms.ullTotalPhys;
Chris@223 156
Chris@223 157 } else {
Chris@223 158
Chris@223 159 /* Fall back to GlobalMemoryStatus which is always available.
Chris@223 160 but returns wrong results for physical memory > 4GB */
Chris@223 161
Chris@223 162 MEMORYSTATUS ms;
Chris@223 163 GlobalMemoryStatus(&ms);
Chris@223 164 wavail = ms.dwAvailPhys;
Chris@223 165 wtotal = ms.dwTotalPhys;
Chris@223 166 }
Chris@223 167
Chris@223 168 DWORDLONG size = wavail / 1048576;
Chris@223 169 if (size > INT_MAX) size = INT_MAX;
Chris@223 170 available = int(size);
Chris@223 171
Chris@223 172 size = wtotal / 1048576;
Chris@223 173 if (size > INT_MAX) size = INT_MAX;
Chris@223 174 total = int(size);
Chris@223 175
Chris@223 176 return;
Chris@223 177
Chris@223 178 #else
Chris@223 179 #ifdef __APPLE__
Chris@223 180
Chris@223 181 unsigned int val;
Chris@223 182 int mib[2];
Chris@223 183 size_t size_sys;
Chris@223 184
Chris@223 185 mib[0] = CTL_HW;
Chris@223 186
Chris@223 187 mib[1] = HW_PHYSMEM;
Chris@223 188 size_sys = sizeof(val);
Chris@223 189 sysctl(mib, 2, &val, &size_sys, NULL, 0);
Chris@223 190 if (val) total = val / 1048576;
Chris@223 191
Chris@223 192 mib[1] = HW_USERMEM;
Chris@223 193 size_sys = sizeof(val);
Chris@223 194 sysctl(mib, 2, &val, &size_sys, NULL, 0);
Chris@223 195 if (val) available = val / 1048576;
Chris@223 196
Chris@223 197 return;
Chris@223 198
Chris@223 199 #else
Chris@223 200
Chris@223 201 FILE *meminfo = fopen("/proc/meminfo", "r");
Chris@223 202 if (!meminfo) return;
Chris@223 203
Chris@223 204 char buf[256];
Chris@223 205 while (!feof(meminfo)) {
Chris@223 206 fgets(buf, 256, meminfo);
Chris@223 207 bool isMemFree = (strncmp(buf, "MemFree:", 8) == 0);
Chris@223 208 bool isMemTotal = (!isMemFree && (strncmp(buf, "MemTotal:", 9) == 0));
Chris@223 209 if (isMemFree || isMemTotal) {
Chris@223 210 QString line = QString(buf).trimmed();
Chris@223 211 QStringList elements = line.split(' ', QString::SkipEmptyParts);
Chris@223 212 QString unit = "kB";
Chris@223 213 if (elements.size() > 2) unit = elements[2];
Chris@223 214 int size = elements[1].toInt();
Chris@223 215 // std::cerr << "have size \"" << size << "\", unit \""
Chris@223 216 // << unit.toStdString() << "\"" << std::endl;
Chris@223 217 if (unit.toLower() == "gb") size = size * 1024;
Chris@223 218 else if (unit.toLower() == "mb") size = size;
Chris@223 219 else if (unit.toLower() == "kb") size = size / 1024;
Chris@223 220 else size = size / 1048576;
Chris@223 221
Chris@223 222 if (isMemFree) available = size;
Chris@223 223 else total = size;
Chris@223 224 }
Chris@223 225 if (available != -1 && total != -1) {
Chris@223 226 fclose(meminfo);
Chris@223 227 return;
Chris@223 228 }
Chris@223 229 }
Chris@223 230 fclose(meminfo);
Chris@223 231
Chris@223 232 return;
Chris@223 233
Chris@223 234 #endif
Chris@223 235 #endif
Chris@223 236 }
Chris@223 237
Chris@223 238 int
Chris@223 239 GetDiscSpaceMBAvailable(const char *path)
Chris@223 240 {
Chris@223 241 #ifdef _WIN32
Chris@223 242 ULARGE_INTEGER available, total, totalFree;
Chris@223 243 if (GetDiskFreeSpaceExA(path, &available, &total, &totalFree)) {
Chris@223 244 __int64 a = available.QuadPart;
Chris@223 245 a /= 1048576;
Chris@223 246 if (a > INT_MAX) a = INT_MAX;
Chris@223 247 return int(a);
Chris@223 248 } else {
Chris@223 249 std::cerr << "WARNING: GetDiskFreeSpaceEx failed: error code "
Chris@223 250 << GetLastError() << std::endl;
Chris@223 251 return -1;
Chris@223 252 }
Chris@223 253 #else
Chris@223 254 struct statvfs buf;
Chris@223 255 if (!statvfs(path, &buf)) {
Chris@223 256 // do the multiplies and divides in this order to reduce the
Chris@223 257 // likelihood of arithmetic overflow
Chris@223 258 std::cerr << "statvfs(" << path << ") says available: " << buf.f_bavail << ", block size: " << buf.f_bsize << std::endl;
Chris@223 259 uint64_t available = ((buf.f_bavail / 1024) * buf.f_bsize) / 1024;
Chris@223 260 if (available > INT_MAX) available = INT_MAX;
Chris@223 261 return int(available);
Chris@223 262 } else {
Chris@223 263 perror("statvfs failed");
Chris@223 264 return -1;
Chris@223 265 }
Chris@223 266 #endif
Chris@223 267 }
Chris@303 268
Chris@303 269 static char *startupLocale = 0;
Chris@303 270
Chris@303 271 void
Chris@303 272 StoreStartupLocale()
Chris@303 273 {
Chris@303 274 char *loc = setlocale(LC_ALL, 0);
Chris@303 275 if (!loc) return;
Chris@303 276 if (startupLocale) free(startupLocale);
Chris@303 277 startupLocale = strdup(loc);
Chris@303 278 }
Chris@303 279
Chris@303 280 void
Chris@303 281 RestoreStartupLocale()
Chris@303 282 {
Chris@303 283 if (!startupLocale) {
Chris@303 284 setlocale(LC_ALL, "");
Chris@303 285 } else {
Chris@303 286 setlocale(LC_ALL, startupLocale);
Chris@303 287 }
Chris@303 288 }
Chris@223 289
Chris@223 290 double mod(double x, double y) { return x - (y * floor(x / y)); }
Chris@223 291 float modf(float x, float y) { return x - (y * floorf(x / y)); }
Chris@223 292
Chris@223 293 double princarg(double a) { return mod(a + M_PI, -2 * M_PI) + M_PI; }
Chris@223 294 float princargf(float a) { return modf(a + M_PI, -2 * M_PI) + M_PI; }
Chris@223 295