Chris@222: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@222: Chris@222: /* Chris@222: Sonic Visualiser Chris@222: An audio file viewer and annotation editor. Chris@222: Centre for Digital Music, Queen Mary, University of London. Chris@222: This file copyright 2006 Chris Cannam and QMUL. Chris@222: Chris@222: This program is free software; you can redistribute it and/or Chris@222: modify it under the terms of the GNU General Public License as Chris@222: published by the Free Software Foundation; either version 2 of the Chris@222: License, or (at your option) any later version. See the file Chris@222: COPYING included with this distribution for more information. Chris@222: */ Chris@222: Chris@222: #include "System.h" Chris@222: Chris@222: #include Chris@222: #include Chris@222: Chris@222: #include Chris@222: Chris@222: #ifndef _WIN32 Chris@222: #include Chris@222: #include Chris@222: #include Chris@222: #endif Chris@222: Chris@222: #ifdef __APPLE__ Chris@222: #include Chris@222: #include Chris@222: #endif Chris@222: Chris@222: #include Chris@222: Chris@222: #ifdef _WIN32 Chris@222: Chris@222: extern "C" { Chris@222: Chris@222: void usleep(unsigned long usec) Chris@222: { Chris@222: ::Sleep(usec / 1000); Chris@222: } Chris@222: Chris@222: void gettimeofday(struct timeval *tv, void *tz) Chris@222: { Chris@222: union { Chris@222: long long ns100; Chris@222: FILETIME ft; Chris@222: } now; Chris@222: Chris@222: ::GetSystemTimeAsFileTime(&now.ft); Chris@222: tv->tv_usec = (long)((now.ns100 / 10LL) % 1000000LL); Chris@222: tv->tv_sec = (long)((now.ns100 - 116444736000000000LL) / 10000000LL); Chris@222: } Chris@222: Chris@222: } Chris@222: Chris@222: #endif Chris@222: Chris@222: ProcessStatus Chris@222: GetProcessStatus(int pid) Chris@222: { Chris@222: #ifdef _WIN32 Chris@222: HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); Chris@222: if (!handle) { Chris@222: return ProcessNotRunning; Chris@222: } else { Chris@222: CloseHandle(handle); Chris@222: return ProcessRunning; Chris@222: } Chris@222: #else Chris@222: if (kill(getpid(), 0) == 0) { Chris@222: if (kill(pid, 0) == 0) { Chris@222: return ProcessRunning; Chris@222: } else { Chris@222: return ProcessNotRunning; Chris@222: } Chris@222: } else { Chris@222: return UnknownProcessStatus; Chris@222: } Chris@222: #endif Chris@222: } Chris@222: Chris@222: #ifdef _WIN32 Chris@222: /* MEMORYSTATUSEX is missing from older Windows headers, so define a Chris@222: local replacement. This trick from MinGW source code. Ugh */ Chris@222: typedef struct Chris@222: { Chris@222: DWORD dwLength; Chris@222: DWORD dwMemoryLoad; Chris@222: DWORDLONG ullTotalPhys; Chris@222: DWORDLONG ullAvailPhys; Chris@222: DWORDLONG ullTotalPageFile; Chris@222: DWORDLONG ullAvailPageFile; Chris@222: DWORDLONG ullTotalVirtual; Chris@222: DWORDLONG ullAvailVirtual; Chris@222: DWORDLONG ullAvailExtendedVirtual; Chris@222: } lMEMORYSTATUSEX; Chris@222: typedef WINBOOL (WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*); Chris@222: #endif Chris@222: Chris@222: void Chris@222: GetRealMemoryMBAvailable(int &available, int &total) Chris@222: { Chris@222: available = -1; Chris@222: total = -1; Chris@222: Chris@222: #ifdef _WIN32 Chris@222: Chris@222: static bool checked = false; Chris@222: static bool exFound = false; Chris@222: static PFN_MS_EX ex; Chris@222: Chris@222: if (!checked) { Chris@222: Chris@222: HMODULE h = GetModuleHandleA("kernel32.dll"); Chris@222: Chris@222: if (h) { Chris@222: if ((ex = (PFN_MS_EX)GetProcAddress(h, "GlobalMemoryStatusEx"))) { Chris@222: exFound = true; Chris@222: } Chris@222: } Chris@222: Chris@222: checked = true; Chris@222: } Chris@222: Chris@222: DWORDLONG wavail = 0; Chris@222: DWORDLONG wtotal = 0; Chris@222: Chris@222: if (exFound) { Chris@222: Chris@222: lMEMORYSTATUSEX lms; Chris@222: lms.dwLength = sizeof(lms); Chris@222: if (!ex(&lms)) { Chris@222: std::cerr << "WARNING: GlobalMemoryStatusEx failed: error code " Chris@222: << GetLastError() << std::endl; Chris@222: return; Chris@222: } Chris@222: wavail = lms.ullAvailPhys; Chris@222: wtotal = lms.ullTotalPhys; Chris@222: Chris@222: } else { Chris@222: Chris@222: /* Fall back to GlobalMemoryStatus which is always available. Chris@222: but returns wrong results for physical memory > 4GB */ Chris@222: Chris@222: MEMORYSTATUS ms; Chris@222: GlobalMemoryStatus(&ms); Chris@222: wavail = ms.dwAvailPhys; Chris@222: wtotal = ms.dwTotalPhys; Chris@222: } Chris@222: Chris@222: DWORDLONG size = wavail / 1048576; Chris@222: if (size > INT_MAX) size = INT_MAX; Chris@222: available = int(size); Chris@222: Chris@222: size = wtotal / 1048576; Chris@222: if (size > INT_MAX) size = INT_MAX; Chris@222: total = int(size); Chris@222: Chris@222: return; Chris@222: Chris@222: #else Chris@222: #ifdef __APPLE__ Chris@222: Chris@222: unsigned int val; Chris@222: int mib[2]; Chris@222: size_t size_sys; Chris@222: Chris@222: mib[0] = CTL_HW; Chris@222: Chris@222: mib[1] = HW_PHYSMEM; Chris@222: size_sys = sizeof(val); Chris@222: sysctl(mib, 2, &val, &size_sys, NULL, 0); Chris@222: if (val) total = val / 1048576; Chris@222: Chris@222: mib[1] = HW_USERMEM; Chris@222: size_sys = sizeof(val); Chris@222: sysctl(mib, 2, &val, &size_sys, NULL, 0); Chris@222: if (val) available = val / 1048576; Chris@222: Chris@222: return; Chris@222: Chris@222: #else Chris@222: Chris@222: FILE *meminfo = fopen("/proc/meminfo", "r"); Chris@222: if (!meminfo) return; Chris@222: Chris@222: char buf[256]; Chris@222: while (!feof(meminfo)) { Chris@222: fgets(buf, 256, meminfo); Chris@222: bool isMemFree = (strncmp(buf, "MemFree:", 8) == 0); Chris@222: bool isMemTotal = (!isMemFree && (strncmp(buf, "MemTotal:", 9) == 0)); Chris@222: if (isMemFree || isMemTotal) { Chris@222: QString line = QString(buf).trimmed(); Chris@222: QStringList elements = line.split(' ', QString::SkipEmptyParts); Chris@222: QString unit = "kB"; Chris@222: if (elements.size() > 2) unit = elements[2]; Chris@222: int size = elements[1].toInt(); Chris@222: // std::cerr << "have size \"" << size << "\", unit \"" Chris@222: // << unit.toStdString() << "\"" << std::endl; Chris@222: if (unit.toLower() == "gb") size = size * 1024; Chris@222: else if (unit.toLower() == "mb") size = size; Chris@222: else if (unit.toLower() == "kb") size = size / 1024; Chris@222: else size = size / 1048576; Chris@222: Chris@222: if (isMemFree) available = size; Chris@222: else total = size; Chris@222: } Chris@222: if (available != -1 && total != -1) { Chris@222: fclose(meminfo); Chris@222: return; Chris@222: } Chris@222: } Chris@222: fclose(meminfo); Chris@222: Chris@222: return; Chris@222: Chris@222: #endif Chris@222: #endif Chris@222: } Chris@222: Chris@222: int Chris@222: GetDiscSpaceMBAvailable(const char *path) Chris@222: { Chris@222: #ifdef _WIN32 Chris@222: ULARGE_INTEGER available, total, totalFree; Chris@222: if (GetDiskFreeSpaceExA(path, &available, &total, &totalFree)) { Chris@222: __int64 a = available.QuadPart; Chris@222: a /= 1048576; Chris@222: if (a > INT_MAX) a = INT_MAX; Chris@222: return int(a); Chris@222: } else { Chris@222: std::cerr << "WARNING: GetDiskFreeSpaceEx failed: error code " Chris@222: << GetLastError() << std::endl; Chris@222: return -1; Chris@222: } Chris@222: #else Chris@222: struct statvfs buf; Chris@222: if (!statvfs(path, &buf)) { Chris@222: // do the multiplies and divides in this order to reduce the Chris@222: // likelihood of arithmetic overflow Chris@222: std::cerr << "statvfs(" << path << ") says available: " << buf.f_bavail << ", block size: " << buf.f_bsize << std::endl; Chris@222: uint64_t available = ((buf.f_bavail / 1024) * buf.f_bsize) / 1024; Chris@222: if (available > INT_MAX) available = INT_MAX; Chris@222: return int(available); Chris@222: } else { Chris@222: perror("statvfs failed"); Chris@222: return -1; Chris@222: } Chris@222: #endif Chris@222: } Chris@222: Chris@222: Chris@222: double mod(double x, double y) { return x - (y * floor(x / y)); } Chris@222: float modf(float x, float y) { return x - (y * floorf(x / y)); } Chris@222: Chris@222: double princarg(double a) { return mod(a + M_PI, -2 * M_PI) + M_PI; } Chris@222: float princargf(float a) { return modf(a + M_PI, -2 * M_PI) + M_PI; } Chris@222: