2 * Copyright (C) 2005-2008 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
23 #include "SystemInfo.h"
27 #include <sys/utsname.h>
29 #include "utils/GUIInfoManager.h"
30 #include "FileSystem/FileCurl.h"
32 #include "Application.h"
33 #include "GraphicContext.h"
34 #include "WindowingFactory.h"
36 #include "LocalizeStrings.h"
38 #include "utils/TimeUtils.h"
44 #include "osx/CocoaInterface.h"
49 CSysInfoJob::CSysInfoJob()
53 bool CSysInfoJob::DoWork()
55 m_info
.systemUptime
= GetSystemUpTime(false);
56 m_info
.systemTotalUptime
= GetSystemUpTime(true);
57 m_info
.internetState
= GetInternetState();
58 m_info
.videoEncoder
= GetVideoEncoder();
59 m_info
.cpuFrequency
= GetCPUFreqInfo();
60 m_info
.kernelVersion
= CSysInfo::GetKernelVersion();
61 m_info
.macAddress
= GetMACAddress();
65 const CSysData
&CSysInfoJob::GetData() const
70 CStdString
CSysInfoJob::GetCPUFreqInfo()
72 CStdString strCPUFreq
;
73 double CPUFreq
= GetCPUFrequency();
74 strCPUFreq
.Format("%4.2fMHz", CPUFreq
);
78 CSysData::INTERNET_STATE
CSysInfoJob::GetInternetState()
80 // Internet connection state!
81 XFILE::CFileCurl http
;
82 if (http
.IsInternet())
83 return CSysData::CONNECTED
;
84 if (http
.IsInternet(false))
85 return CSysData::NO_DNS
;
86 return CSysData::DISCONNECTED
;
89 CStdString
CSysInfoJob::GetMACAddress()
91 #if defined(HAS_LINUX_NETWORK)
92 CNetworkInterface
* iface
= g_application
.getNetwork().GetFirstConnectedInterface();
94 return iface
->GetMacAddress();
99 CStdString
CSysInfoJob::GetVideoEncoder()
101 return "GPU: " + g_Windowing
.GetRenderRenderer();
104 double CSysInfoJob::GetCPUFrequency()
106 #if defined (_LINUX) || defined(_WIN32)
107 return double (g_cpuInfo
.getCPUFrequency());
113 bool CSysInfoJob::SystemUpTime(int iInputMinutes
, int &iMinutes
, int &iHours
, int &iDays
)
115 iMinutes
=0;iHours
=0;iDays
=0;
116 iMinutes
= iInputMinutes
;
117 if (iMinutes
>= 60) // Hour's
119 iHours
= iMinutes
/ 60;
120 iMinutes
= iMinutes
- (iHours
*60);
122 if (iHours
>= 24) // Days
125 iHours
= iHours
- (iDays
* 24);
130 CStdString
CSysInfoJob::GetSystemUpTime(bool bTotalUptime
)
132 CStdString strSystemUptime
;
133 int iInputMinutes
, iMinutes
,iHours
,iDays
;
138 iInputMinutes
= g_settings
.m_iSystemTimeTotalUp
+ ((int)(CTimeUtils::GetTimeMS() / 60000));
143 iInputMinutes
= (int)(CTimeUtils::GetTimeMS() / 60000);
146 SystemUpTime(iInputMinutes
,iMinutes
, iHours
, iDays
);
149 strSystemUptime
.Format("%i %s, %i %s, %i %s",
150 iDays
,g_localizeStrings
.Get(12393),
151 iHours
,g_localizeStrings
.Get(12392),
152 iMinutes
, g_localizeStrings
.Get(12391));
154 else if (iDays
== 0 && iHours
>= 1 )
156 strSystemUptime
.Format("%i %s, %i %s",
157 iHours
,g_localizeStrings
.Get(12392),
158 iMinutes
, g_localizeStrings
.Get(12391));
160 else if (iDays
== 0 && iHours
== 0 && iMinutes
>= 0)
162 strSystemUptime
.Format("%i %s",
163 iMinutes
, g_localizeStrings
.Get(12391));
165 return strSystemUptime
;
168 CStdString
CSysInfo::TranslateInfo(int info
) const
172 case SYSTEM_VIDEO_ENCODER_INFO
:
173 return m_info
.videoEncoder
;
174 case NETWORK_MAC_ADDRESS
:
175 return m_info
.macAddress
;
176 case SYSTEM_KERNEL_VERSION
:
177 return m_info
.kernelVersion
;
178 case SYSTEM_CPUFREQUENCY
:
179 return m_info
.cpuFrequency
;
181 return m_info
.systemUptime
;
182 case SYSTEM_TOTALUPTIME
:
183 return m_info
.systemTotalUptime
;
184 case SYSTEM_INTERNET_STATE
:
185 if (m_info
.internetState
== CSysData::CONNECTED
)
186 return g_localizeStrings
.Get(13296);
187 else if (m_info
.internetState
== CSysData::NO_DNS
)
188 return g_localizeStrings
.Get(13274);
190 return g_localizeStrings
.Get(13297);
196 void CSysInfo::Reset()
201 CSysInfo::CSysInfo(void) : CInfoLoader(15 * 1000)
205 CSysInfo::~CSysInfo()
209 bool CSysInfo::GetDiskSpace(const CStdString drive
,int& iTotal
, int& iTotalFree
, int& iTotalUsed
, int& iPercentFree
, int& iPercentUsed
)
212 ULARGE_INTEGER ULTotal
= { { 0 } };
213 ULARGE_INTEGER ULTotalFree
= { { 0 } };
215 if( !drive
.IsEmpty() && !drive
.Equals("*") )
218 UINT uidriveType
= GetDriveType(( drive
+ ":\\" ));
219 if(uidriveType
!= DRIVE_UNKNOWN
&& uidriveType
!= DRIVE_NO_ROOT_DIR
)
221 bRet
= ( 0 != GetDiskFreeSpaceEx( ( drive
+ ":\\" ), NULL
, &ULTotal
, &ULTotalFree
) );
225 ULARGE_INTEGER ULTotalTmp
= { { 0 } };
226 ULARGE_INTEGER ULTotalFreeTmp
= { { 0 } };
228 char* pcBuffer
= NULL
;
229 DWORD dwStrLength
= GetLogicalDriveStrings( 0, pcBuffer
);
230 if( dwStrLength
!= 0 )
233 pcBuffer
= new char [dwStrLength
];
234 GetLogicalDriveStrings( dwStrLength
, pcBuffer
);
237 if( DRIVE_FIXED
== GetDriveType( pcBuffer
+ iPos
) &&
238 GetDiskFreeSpaceEx( ( pcBuffer
+ iPos
), NULL
, &ULTotal
, &ULTotalFree
) )
240 ULTotalTmp
.QuadPart
+= ULTotal
.QuadPart
;
241 ULTotalFreeTmp
.QuadPart
+= ULTotalFree
.QuadPart
;
243 iPos
+= (strlen( pcBuffer
+ iPos
) + 1 );
244 }while( strlen( pcBuffer
+ iPos
) > 0 );
247 #else // for linux and osx
248 static const char *drv_letter
[] = { "C:\\", "E:\\", "F:\\", "G:\\", "X:\\", "Y:\\", "Z:\\", NULL
};
249 for( int i
= 0; drv_letter
[i
]; i
++)
251 if( GetDiskFreeSpaceEx( drv_letter
[i
], NULL
, &ULTotal
, &ULTotalFree
) )
253 ULTotalTmp
.QuadPart
+= ULTotal
.QuadPart
;
254 ULTotalFreeTmp
.QuadPart
+= ULTotalFree
.QuadPart
;
258 if( ULTotalTmp
.QuadPart
|| ULTotalFreeTmp
.QuadPart
)
260 ULTotal
.QuadPart
= ULTotalTmp
.QuadPart
;
261 ULTotalFree
.QuadPart
= ULTotalFreeTmp
.QuadPart
;
268 iTotal
= (int)( ULTotal
.QuadPart
/ MB
);
269 iTotalFree
= (int)( ULTotalFree
.QuadPart
/ MB
);
270 iTotalUsed
= iTotal
- iTotalFree
;
271 iPercentUsed
= (int)( 100.0f
* ( ULTotal
.QuadPart
- ULTotalFree
.QuadPart
) / ULTotal
.QuadPart
+ 0.5f
);
272 iPercentFree
= 100 - iPercentUsed
;
278 CStdString
CSysInfo::GetXBVerInfo()
280 return "CPU: " + g_cpuInfo
.getCPUModel();
283 bool CSysInfo::IsAeroDisabled()
286 OSVERSIONINFOEX osvi
;
287 ZeroMemory(&osvi
, sizeof(OSVERSIONINFOEX
));
288 osvi
.dwOSVersionInfoSize
= sizeof(osvi
);
290 if (GetVersionEx((OSVERSIONINFO
*)&osvi
))
292 if (osvi
.dwMajorVersion
== 5)
293 return true; // windows XP -> no Aero
295 BOOL aeroEnabled
= FALSE
;
296 HRESULT res
= DwmIsCompositionEnabled(&aeroEnabled
);
304 bool CSysInfo::IsVistaOrHigher()
307 OSVERSIONINFOEX osvi
;
308 ZeroMemory(&osvi
, sizeof(OSVERSIONINFOEX
));
309 osvi
.dwOSVersionInfoSize
= sizeof(osvi
);
311 if (GetVersionEx((OSVERSIONINFO
*)&osvi
))
313 if (osvi
.dwMajorVersion
>= 6)
320 CStdString
CSysInfo::GetKernelVersion()
326 CStdString strKernel
;
327 strKernel
.Format("%s %s %s %s", un
.sysname
, un
.release
, un
.version
, un
.machine
);
333 OSVERSIONINFOEX osvi
;
336 ZeroMemory(&si
, sizeof(SYSTEM_INFO
));
337 ZeroMemory(&osvi
, sizeof(OSVERSIONINFOEX
));
341 osvi
.dwOSVersionInfoSize
= sizeof(osvi
);
342 CStdString strKernel
= "Windows ";
344 if (GetVersionEx((OSVERSIONINFO
*)&osvi
))
346 if ( osvi
.dwMajorVersion
== 6 )
348 if (osvi
.dwMinorVersion
== 0)
350 if( osvi
.wProductType
== VER_NT_WORKSTATION
)
351 strKernel
.append("Vista");
353 strKernel
.append("Server 2008");
354 } else if (osvi
.dwMinorVersion
== 1)
356 if( osvi
.wProductType
== VER_NT_WORKSTATION
)
357 strKernel
.append("7");
359 strKernel
.append("Server 2008 R2");
362 if ( si
.wProcessorArchitecture
==PROCESSOR_ARCHITECTURE_AMD64
|| si
.wProcessorArchitecture
==PROCESSOR_ARCHITECTURE_IA64
)
363 strKernel
.append(", 64-bit Native");
364 else if (si
.wProcessorArchitecture
==PROCESSOR_ARCHITECTURE_INTEL
)
366 BOOL bIsWow
= FALSE
;;
367 if(IsWow64Process(GetCurrentProcess(), &bIsWow
))
371 GetNativeSystemInfo(&si
);
372 if (si
.wProcessorArchitecture
== PROCESSOR_ARCHITECTURE_AMD64
|| si
.wProcessorArchitecture
== PROCESSOR_ARCHITECTURE_IA64
)
373 strKernel
.append(", 64-bit (WoW)");
377 strKernel
.append(", 32-bit");
381 strKernel
.append(", 32-bit");
384 else if ( osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 2 )
386 if( osvi
.wProductType
== VER_NT_WORKSTATION
&& si
.wProcessorArchitecture
==PROCESSOR_ARCHITECTURE_AMD64
)
388 strKernel
.append("XP Professional x64 Edition");
391 else if ( osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 1 )
393 strKernel
.append("XP ");
394 if( osvi
.wSuiteMask
& VER_SUITE_PERSONAL
)
395 strKernel
.append("Home Edition" );
397 strKernel
.append("Professional" );
399 else if ( osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 0 )
401 strKernel
.append("2000");
404 if( _tcslen(osvi
.szCSDVersion
) > 0 )
406 strKernel
.append(" ");
407 strKernel
.append(osvi
.szCSDVersion
);
410 strBuild
.Format(" build %d",osvi
.dwBuildNumber
);
411 strKernel
+= strBuild
;
417 bool CSysInfo::HasInternet()
419 if (m_info
.internetState
!= CSysData::UNKNOWN
)
420 return m_info
.internetState
== CSysData::CONNECTED
;
421 return (m_info
.internetState
= CSysInfoJob::GetInternetState()) == CSysData::CONNECTED
;
424 CStdString
CSysInfo::GetHddSpaceInfo(int drive
, bool shortText
)
427 return GetHddSpaceInfo( percent
, drive
, shortText
);
430 CStdString
CSysInfo::GetHddSpaceInfo(int& percent
, int drive
, bool shortText
)
432 int total
, totalFree
, totalUsed
, percentFree
, percentused
;
439 case SYSTEM_FREE_SPACE
:
440 case SYSTEM_USED_SPACE
:
441 case SYSTEM_TOTAL_SPACE
:
442 case SYSTEM_FREE_SPACE_PERCENT
:
443 case SYSTEM_USED_SPACE_PERCENT
:
444 bRet
= g_sysinfo
.GetDiskSpace("",total
, totalFree
, totalUsed
, percentFree
, percentused
);
446 case LCD_FREE_SPACE_C
:
447 case SYSTEM_FREE_SPACE_C
:
448 case SYSTEM_USED_SPACE_C
:
449 case SYSTEM_TOTAL_SPACE_C
:
450 case SYSTEM_FREE_SPACE_PERCENT_C
:
451 case SYSTEM_USED_SPACE_PERCENT_C
:
453 bRet
= g_sysinfo
.GetDiskSpace("C",total
, totalFree
, totalUsed
, percentFree
, percentused
);
455 case LCD_FREE_SPACE_E
:
456 case SYSTEM_FREE_SPACE_E
:
457 case SYSTEM_USED_SPACE_E
:
458 case SYSTEM_TOTAL_SPACE_E
:
459 case SYSTEM_FREE_SPACE_PERCENT_E
:
460 case SYSTEM_USED_SPACE_PERCENT_E
:
462 bRet
= g_sysinfo
.GetDiskSpace("E",total
, totalFree
, totalUsed
, percentFree
, percentused
);
464 case LCD_FREE_SPACE_F
:
465 case SYSTEM_FREE_SPACE_F
:
466 case SYSTEM_USED_SPACE_F
:
467 case SYSTEM_TOTAL_SPACE_F
:
468 case SYSTEM_FREE_SPACE_PERCENT_F
:
469 case SYSTEM_USED_SPACE_PERCENT_F
:
471 bRet
= g_sysinfo
.GetDiskSpace("F",total
, totalFree
, totalUsed
, percentFree
, percentused
);
473 case LCD_FREE_SPACE_G
:
474 case SYSTEM_FREE_SPACE_G
:
475 case SYSTEM_USED_SPACE_G
:
476 case SYSTEM_TOTAL_SPACE_G
:
477 case SYSTEM_FREE_SPACE_PERCENT_G
:
478 case SYSTEM_USED_SPACE_PERCENT_G
:
480 bRet
= g_sysinfo
.GetDiskSpace("G",total
, totalFree
, totalUsed
, percentFree
, percentused
);
482 case SYSTEM_USED_SPACE_X
:
483 case SYSTEM_FREE_SPACE_X
:
484 case SYSTEM_TOTAL_SPACE_X
:
486 bRet
= g_sysinfo
.GetDiskSpace("X",total
, totalFree
, totalUsed
, percentFree
, percentused
);
488 case SYSTEM_USED_SPACE_Y
:
489 case SYSTEM_FREE_SPACE_Y
:
490 case SYSTEM_TOTAL_SPACE_Y
:
492 bRet
= g_sysinfo
.GetDiskSpace("Y",total
, totalFree
, totalUsed
, percentFree
, percentused
);
494 case SYSTEM_USED_SPACE_Z
:
495 case SYSTEM_FREE_SPACE_Z
:
496 case SYSTEM_TOTAL_SPACE_Z
:
498 bRet
= g_sysinfo
.GetDiskSpace("Z",total
, totalFree
, totalUsed
, percentFree
, percentused
);
507 case LCD_FREE_SPACE_C
:
508 case LCD_FREE_SPACE_E
:
509 case LCD_FREE_SPACE_F
:
510 case LCD_FREE_SPACE_G
:
511 strRet
.Format("%iMB", totalFree
);
513 case SYSTEM_FREE_SPACE
:
514 case SYSTEM_FREE_SPACE_C
:
515 case SYSTEM_FREE_SPACE_E
:
516 case SYSTEM_FREE_SPACE_F
:
517 case SYSTEM_FREE_SPACE_G
:
518 case SYSTEM_FREE_SPACE_X
:
519 case SYSTEM_FREE_SPACE_Y
:
520 case SYSTEM_FREE_SPACE_Z
:
521 percent
= percentFree
;
523 case SYSTEM_USED_SPACE
:
524 case SYSTEM_USED_SPACE_C
:
525 case SYSTEM_USED_SPACE_E
:
526 case SYSTEM_USED_SPACE_F
:
527 case SYSTEM_USED_SPACE_G
:
528 case SYSTEM_USED_SPACE_X
:
529 case SYSTEM_USED_SPACE_Y
:
530 case SYSTEM_USED_SPACE_Z
:
531 percent
= percentused
;
539 case SYSTEM_FREE_SPACE
:
540 case SYSTEM_FREE_SPACE_C
:
541 case SYSTEM_FREE_SPACE_E
:
542 case SYSTEM_FREE_SPACE_F
:
543 case SYSTEM_FREE_SPACE_G
:
544 case SYSTEM_FREE_SPACE_X
:
545 case SYSTEM_FREE_SPACE_Y
:
546 case SYSTEM_FREE_SPACE_Z
:
547 if (strDrive
.IsEmpty())
548 strRet
.Format("%i MB %s", totalFree
, g_localizeStrings
.Get(160));
550 strRet
.Format("%s: %i MB %s", strDrive
, totalFree
, g_localizeStrings
.Get(160));
552 case SYSTEM_USED_SPACE
:
553 case SYSTEM_USED_SPACE_C
:
554 case SYSTEM_USED_SPACE_E
:
555 case SYSTEM_USED_SPACE_F
:
556 case SYSTEM_USED_SPACE_G
:
557 case SYSTEM_USED_SPACE_X
:
558 case SYSTEM_USED_SPACE_Y
:
559 case SYSTEM_USED_SPACE_Z
:
560 if (strDrive
.IsEmpty())
561 strRet
.Format("%i MB %s", totalUsed
, g_localizeStrings
.Get(20162));
563 strRet
.Format("%s: %i MB %s", strDrive
, totalUsed
, g_localizeStrings
.Get(20162));
565 case SYSTEM_TOTAL_SPACE
:
566 case SYSTEM_TOTAL_SPACE_C
:
567 case SYSTEM_TOTAL_SPACE_E
:
568 case SYSTEM_TOTAL_SPACE_F
:
569 case SYSTEM_TOTAL_SPACE_G
:
570 if (strDrive
.IsEmpty())
571 strRet
.Format("%i MB %s", total
, g_localizeStrings
.Get(20161));
573 strRet
.Format("%s: %i MB %s", strDrive
, total
, g_localizeStrings
.Get(20161));
575 case SYSTEM_FREE_SPACE_PERCENT
:
576 case SYSTEM_FREE_SPACE_PERCENT_C
:
577 case SYSTEM_FREE_SPACE_PERCENT_E
:
578 case SYSTEM_FREE_SPACE_PERCENT_F
:
579 case SYSTEM_FREE_SPACE_PERCENT_G
:
580 if (strDrive
.IsEmpty())
581 strRet
.Format("%i %% %s", percentFree
, g_localizeStrings
.Get(160));
583 strRet
.Format("%s: %i %% %s", strDrive
, percentFree
, g_localizeStrings
.Get(160));
585 case SYSTEM_USED_SPACE_PERCENT
:
586 case SYSTEM_USED_SPACE_PERCENT_C
:
587 case SYSTEM_USED_SPACE_PERCENT_E
:
588 case SYSTEM_USED_SPACE_PERCENT_F
:
589 case SYSTEM_USED_SPACE_PERCENT_G
:
590 if (strDrive
.IsEmpty())
591 strRet
.Format("%i %% %s", percentused
, g_localizeStrings
.Get(20162));
593 strRet
.Format("%s: %i %% %s", strDrive
, percentused
, g_localizeStrings
.Get(20162));
602 else if (strDrive
.IsEmpty())
603 strRet
= g_localizeStrings
.Get(161);
605 strRet
.Format("%s: %s", strDrive
, g_localizeStrings
.Get(161));
610 #if defined(_LINUX) && !defined(__APPLE__)
611 CStdString
CSysInfo::GetLinuxDistro()
613 static const char* release_file
[] = { "/etc/debian_version",
615 "/etc/mandrake-release",
616 "/etc/fedora-release",
617 "/etc/redhat-release",
618 "/etc/gentoo-release",
619 "/etc/slackware-version",
623 FILE* pipe
= popen("unset PYTHONHOME; unset PYTHONPATH; lsb_release -d | cut -f2", "r");
625 for (int i
= 0; !pipe
&& release_file
[i
]; i
++)
627 CStdString cmd
= "cat ";
628 cmd
+= release_file
[i
];
630 pipe
= popen(cmd
.c_str(), "r");
633 CStdString result
= "Unknown";
636 char buffer
[256] = {'\0'};
637 if (fread(buffer
, sizeof(char), sizeof(buffer
), pipe
) > 0 && !ferror(pipe
))
640 CLog::Log(LOGWARNING
, "Unable to determine Linux distribution");
643 return result
.Trim();
648 CStdString
CSysInfo::GetUnameVersion()
650 CStdString result
= "";
652 FILE* pipe
= popen("uname -rm", "r");
655 char buffer
[256] = {'\0'};
656 if (fread(buffer
, sizeof(char), sizeof(buffer
), pipe
) > 0 && !ferror(pipe
))
659 CLog::Log(LOGWARNING
, "Unable to determine Uname version");
663 return result
.Trim();
667 CStdString
CSysInfo::GetUserAgent()
670 result
= "XBMC/" + g_infoManager
.GetLabel(SYSTEM_BUILD_VERSION
) + " (";
672 result
+= "Windows; ";
673 result
+= GetKernelVersion();
674 #elif defined(__APPLE__)
675 result
+= "Mac OS X; ";
676 result
+= GetUnameVersion();
677 #elif defined(_LINUX)
679 result
+= GetLinuxDistro();
681 result
+= GetUnameVersion();
683 result
+= "; http://www.xbmc.org)";
688 bool CSysInfo::IsAppleTV()
691 #if defined(__APPLE__)
694 std::string hw_model
= "unknown";
696 if (sysctlbyname("hw.model", &buffer
, &len
, NULL
, 0) == 0)
699 if (hw_model
.find("AppleTV") != std::string::npos
)
705 bool CSysInfo::HasVDADecoder()
709 #if defined(__APPLE__)
710 result
= Cocoa_HasVDADecoder();
715 CJob
*CSysInfo::GetJob() const
717 return new CSysInfoJob();
720 void CSysInfo::OnJobComplete(unsigned int jobID
, bool success
, CJob
*job
)
722 m_info
= ((CSysInfoJob
*)job
)->GetData();
723 CInfoLoader::OnJobComplete(jobID
, success
, job
);