annotate system/System.cpp @ 221:07a96a1931c0

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