annotate system/System.cpp @ 222:c7122e70f8ec

Fixes for Windows build
author Chris Cannam
date Thu, 25 Jan 2007 17:41:00 +0000
parents 07a96a1931c0
children bf753a9abf0c
rev   line source
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