1 //===========================================
2 //  Lumina-DE source code
3 //  Copyright (c) 2014, Ken Moore
4 //  Available under the 3-clause BSD license
5 //  See the LICENSE file for full details
6 //===========================================
7 #ifdef __linux__
8 #include <QDebug>
9 #include "LuminaOS.h"
10 #include <unistd.h>
11 #include <stdio.h> // Needed for BUFSIZ
12 
13 //can't read xbrightness settings - assume invalid until set
14 static int screenbrightness = -1;
15 
OSName()16 QString LOS::OSName(){ return "Linux"; }
17 
18 //OS-specific prefix(s)
19 // NOTE: PREFIX, L_ETCDIR, L_SHAREDIR are defined in the OS-detect.pri project file and passed in
LuminaShare()20 QString LOS::LuminaShare(){ return (L_SHAREDIR+"/lumina-desktop/"); } //Install dir for Lumina share files
AppPrefix()21 QString LOS::AppPrefix(){ return "/usr/"; } //Prefix for applications
SysPrefix()22 QString LOS::SysPrefix(){ return "/usr/"; } //Prefix for system
23 
24 //OS-specific application shortcuts (*.desktop files)
ControlPanelShortcut()25 QString LOS::ControlPanelShortcut(){ return ""; } //system control panel
AppStoreShortcut()26 QString LOS::AppStoreShortcut(){ return ""; } //graphical app/pkg manager
27 //OS-specific RSS feeds (Format: QStringList[ <name>::::<url> ]; )
RSSFeeds()28 QStringList LOS::RSSFeeds(){ return QStringList(); }
29 
30 // ==== ExternalDevicePaths() ====
ExternalDevicePaths()31 QStringList LOS::ExternalDevicePaths(){
32     //Returns: QStringList[<type>::::<filesystem>::::<path>]
33       //Note: <type> = [USB, HDRIVE, DVD, SDCARD, UNKNOWN]
34   QStringList devs = LUtils::getCmdOutput("mount");
35   //Now check the output
36   for(int i=0; i<devs.length(); i++){
37     if(devs[i].startsWith("/dev/")){
38       devs[i] = devs[i].simplified();
39       QString type = devs[i].section(" ",0,0);
40       type.remove("/dev/");
41       //Determine the type of hardware device based on the dev node
42       if(type.startsWith("sd") || type.startsWith("nvme")){ type = "HDRIVE"; }
43       else if(type.startsWith("sr")){ type="DVD"; }
44       else if(type.contains("mapper")){ type="LVM"; }
45       else{ type = "UNKNOWN"; }
46       //Now put the device in the proper output format
47       devs[i] = type+"::::"+devs[i].section(" ",4,4)+"::::"+devs[i].section(" ",2,2);
48     }else{
49       //invalid device - remove it from the list
50       devs.removeAt(i);
51       i--;
52     }
53   }
54   return devs;
55 }
56 
57 //Read screen brightness information
ScreenBrightness()58 int LOS::ScreenBrightness(){
59    //Returns: Screen Brightness as a percentage (0-100, with -1 for errors)
60   if(screenbrightness==-1){
61     if(QFile::exists(QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/.currentxbrightness")){
62       int val = LUtils::readFile(QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/.currentxbrightness").join("").simplified().toInt();
63       screenbrightness = val;
64     }
65   }
66   return screenbrightness;
67 
68 }
69 
70 //Set screen brightness
setScreenBrightness(int percent)71 void LOS::setScreenBrightness(int percent){
72   //ensure bounds
73   if(percent<0){percent=0;}
74   else if(percent>100){ percent=100; }
75   // float pf = percent/100.0; //convert to a decimel
76   //Run the command
77   QString cmd = "xbacklight -set %1";
78   // cmd = cmd.arg( QString::number( int(65535*pf) ) );
79   cmd = cmd.arg( QString::number( percent ) );
80   int ret = LUtils::runCmd(cmd);
81   //Save the result for later
82   if(ret!=0){ screenbrightness = -1; }
83   else{ screenbrightness = percent; }
84   LUtils::writeFile(QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/.currentxbrightness", QStringList() << QString::number(screenbrightness), true);
85 
86 }
87 
88 //Read the current volume
audioVolume()89 int LOS::audioVolume(){ //Returns: audio volume as a percentage (0-100, with -1 for errors)
90 QString info = LUtils::getCmdOutput("amixer get Master").join("").simplified();;
91   int out = -1;
92   int start_position, end_position;
93   QString current_volume;
94   if(!info.isEmpty()){
95      start_position = info.indexOf("[");
96      start_position++;
97      end_position = info.indexOf("%");
98      current_volume = info.mid(start_position, end_position - start_position);
99      out = current_volume.toInt();
100   }
101   return out;
102 
103 
104 }
105 
106 //Set the current volume
setAudioVolume(int percent)107 void LOS::setAudioVolume(int percent){
108   if(percent<0){percent=0;}
109   else if(percent>100){percent=100;}
110   QString info = "amixer set Master " + QString::number(percent) + "%";
111   //Run Command
112   LUtils::runCmd(info);
113 }
114 
115 //Change the current volume a set amount (+ or -)
changeAudioVolume(int percentdiff)116 void LOS::changeAudioVolume(int percentdiff){
117   int old_volume = audioVolume();
118   int new_volume = old_volume + percentdiff;
119   if (new_volume < 0)
120       new_volume = 0;
121   if (new_volume > 100)
122       new_volume = 100;
123   qDebug() << "Setting new volume to: " << new_volume;
124   setAudioVolume(new_volume);
125 }
126 
127 //Check if a graphical audio mixer is installed
hasMixerUtility()128 bool LOS::hasMixerUtility(){
129   return QFile::exists(LOS::AppPrefix() + "bin/pavucontrol");
130 }
131 
132 //Launch the graphical audio mixer utility
startMixerUtility()133 void LOS::startMixerUtility(){
134   QProcess::startDetached(LOS::AppPrefix() + "bin/pavucontrol");
135 }
136 
137 //Check for user system permission (shutdown/restart)
userHasShutdownAccess()138 bool LOS::userHasShutdownAccess(){
139   return true; //not implemented yet
140 }
141 
142 //Check for whether the system is safe to power off (no updates being perfomed)
systemPerformingUpdates()143 bool LOS::systemPerformingUpdates(){
144   return false; //Not implemented yet
145 }
146 
147 //Return the details of any updates which are waiting to apply on shutdown
systemPendingUpdates()148 QString LOS::systemPendingUpdates(){
149   return "";
150 }
151 
152 //System Shutdown
systemShutdown(bool)153 void LOS::systemShutdown(bool){ //start poweroff sequence
154   //INPUT: skip updates (true/false)
155   QProcess::startDetached("shutdown -P -h now");
156 }
157 
158 //System Restart
systemRestart(bool)159 void LOS::systemRestart(bool){ //start reboot sequence
160   //INPUT: skip updates (true/false)
161   QProcess::startDetached("shutdown -r now");
162 }
163 
164 //Check for suspend support
systemCanSuspend()165 bool LOS::systemCanSuspend(){
166   return false;
167 }
168 
169 //Put the system into the suspend state
systemSuspend()170 void LOS::systemSuspend(){
171 
172 }
173 
174 //Battery Availability
hasBattery()175 bool LOS::hasBattery(){
176   QString my_status = LUtils::getCmdOutput("acpi -b").join("");
177   bool no_battery = my_status.contains("No support");
178   if (no_battery) return false;
179   return true;
180 }
181 
182 //Battery Charge Level
batteryCharge()183 int LOS::batteryCharge(){ //Returns: percent charge (0-100), anything outside that range is counted as an error
184   QString my_status = LUtils::getCmdOutput("acpi -b").join("");
185   int my_start = my_status.indexOf("%");
186   // get the number right before the % sign
187   int my_end = my_start;
188   my_start--;
189   while ( (my_status[my_start] != ' ') && (my_start > 0) )
190       my_start--;
191   my_start++;
192   int my_charge = my_status.mid(my_start, my_end - my_start).toInt();
193   if ( (my_charge < 0) || (my_charge > 100) ) return -1;
194   return my_charge;
195 }
196 
197 //Battery Charging State
198 // Many possible values are returned if the laptop is plugged in
199 // these include "Unknown, Full and No support.
200 // However, it seems just one status is returned when running
201 // on battery and that is "Discharging". So if the value we get
202 // is NOT Discharging then we assume the battery is charging.
batteryIsCharging()203 bool LOS::batteryIsCharging(){
204   QString my_status = LUtils::getCmdOutput("acpi -b").join("");
205   bool discharging = my_status.contains("Discharging");
206   if (discharging) return false;
207   return true;
208 }
209 
210 //Battery Time Remaining
batterySecondsLeft()211 int LOS::batterySecondsLeft(){ //Returns: estimated number of seconds remaining
212   return 0; //not implemented yet for Linux
213 }
214 
215 //File Checksums
Checksums(QStringList filepaths)216 QStringList LOS::Checksums(QStringList filepaths){ //Return: checksum of the input file
217   QStringList info = LUtils::getCmdOutput("md5sum \""+filepaths.join("\" \"")+"\"");
218   for(int i=0; i<info.length(); i++){
219     // first: md5sum: = error ; second: there's always one empty entry generated by getCmdOutput
220     if( info[i].startsWith("md5sum:") || info[i].isEmpty()){ info.removeAt(i); i--; }
221     else{
222       //Strip out the extra information
223       info[i] = info[i].section(" ",0,0);
224     }
225   }
226  return info;
227 }
228 
229 //file system capacity
FileSystemCapacity(QString dir)230 QString LOS::FileSystemCapacity(QString dir) { //Return: percentage capacity as give by the df command
231   QStringList mountInfo = LUtils::getCmdOutput("df \"" + dir+"\"");
232   QString::SectionFlag skipEmpty = QString::SectionSkipEmpty;
233   //we take the 5th word on the 2 line
234   QString capacity = mountInfo[1].section(" ",4,4, skipEmpty) + " used";
235   return capacity;
236 }
237 
CPUTemperatures()238 QStringList LOS::CPUTemperatures(){ //Returns: List containing the temperature of any CPU's ("50C" for example)
239   return QStringList(); //not implemented yet
240 }
241 
CPUUsagePercent()242 int LOS::CPUUsagePercent(){ //Returns: Overall percentage of the amount of CPU cycles in use (-1 for errors)
243   return -1; //not implemented yet
244 }
245 
MemoryUsagePercent()246 int LOS::MemoryUsagePercent(){
247   return -1; //not implemented yet
248 }
249 
DiskUsage()250 QStringList LOS::DiskUsage(){ //Returns: List of current read/write stats for each device
251   return QStringList(); //not implemented yet
252 }
253 
254 #endif
255