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