diff --git a/.gitignore b/.gitignore
index 65764a4..37da56a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,67 @@
-NvIndicator.geany
+# Created by .ignore support plugin (hsz.mobi)
+### Python template
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.cache
+nosetests.xml
+coverage.xml
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# PyCharm
+.idea/
+.idea
+
+# Geany
+*.geany
+
+# virtualenv
+.project
diff --git a/nvindicator.py b/nvindicator.py
index 470a399..b030b4e 100755
--- a/nvindicator.py
+++ b/nvindicator.py
@@ -2,19 +2,9 @@
"""nvindicator.py: An NVIDIA GPU indicator applet"""
-__author__ = "Jeff Channell"
-__copyright__ = "Copyright 2017, Jeff Channell"
-__credits__ = ["Jeff Channell"]
-__license__ = "GPL"
-__version__ = "1.0.2"
-__maintainer__ = "Jeff Channell"
-__email__ = "me@jeffchannell.com"
-__status__ = "Prototype"
-
-import gi
import signal
import subprocess
-import sys
+import gi
gi.require_version("Gtk", "3.0")
gi.require_version("AppIndicator3", "0.1")
@@ -25,242 +15,275 @@
from lxml import objectify
from subprocess import run
+__author__ = "Jeff Channell"
+__copyright__ = "Copyright 2017, Jeff Channell"
+__credits__ = ["Jeff Channell"]
+__license__ = "GPL"
+__version__ = "1.0.2"
+__maintainer__ = "Jeff Channell"
+__email__ = "me@jeffchannell.com"
+__status__ = "Prototype"
+
+
class NvIndicator:
- def __init__(self):
- # check for nvidia app
- check = run(
- ["nvidia-smi"],
- stdout=subprocess.PIPE,
- universal_newlines=True
- )
-
- # about window init
- self.about = None
-
- # track menus
- self.menus = []
-
- # track gpus
- self.gpus = []
- xml = self.read_nvidia()
-
- # all menus display the driver version
- driver = str(xml.driver_version[0])
-
- for gpu in xml.gpu:
- items = []
-
- # create a new indicator
- ind = appindicator.Indicator.new(
- "NvIndicator",
- "nvidia-settings",
- appindicator.IndicatorCategory.HARDWARE
- )
- ind.set_status(appindicator.IndicatorStatus.ACTIVE)
- menu = Gtk.Menu()
-
- # add an nvidia-settings menu item
- item = Gtk.MenuItem()
- item.set_label("Open NVIDIA Settings")
- item.connect("activate", self.run_nvidia_settings)
- menu.append(item)
-
- # sep
- item = Gtk.SeparatorMenuItem()
- menu.append(item)
-
- # gpu name
- item = Gtk.MenuItem()
- item.set_label(str(gpu.product_name[0]))
- item.connect("activate", self.do_nothing)
- menu.append(item)
-
- # driver version
- item = Gtk.MenuItem()
- item.set_label("Driver\tv{}".format(driver))
- item.connect("activate", self.do_nothing)
- menu.append(item)
-
- # memory usage - update 0
- item = Gtk.MenuItem()
- item.set_label(
- "Using {} of {}".format(
- str(gpu.fb_memory_usage[0].used[0]),
- str(gpu.fb_memory_usage[0].total[0])
- )
- )
- item.connect("activate", self.do_nothing)
- items.append(item)
- menu.append(item)
-
- # temperature - update 1
- item = Gtk.MenuItem()
- item.set_label(
- "Temperature\t\t{}".format(
- str(gpu.temperature[0].gpu_temp[0])
- )
- )
- item.get_children()[0].set_justify(Gtk.Justification.FILL)
- item.connect("activate", self.do_nothing)
- items.append(item)
- menu.append(item)
-
- # power draw - update 2
- item = Gtk.MenuItem()
- item.set_label(
- "Power Draw\t\t{}".format(
- str(gpu.power_readings[0].power_draw[0])
- )
- )
- item.get_children()[0].set_justify(Gtk.Justification.FILL)
- item.connect("activate", self.do_nothing)
- items.append(item)
- menu.append(item)
-
- # processes - update 3
- item = Gtk.MenuItem()
- item.set_label(
- "Processes\t\t\t{}".format(
- str(len(gpu.processes))
- )
- )
- item.get_children()[0].set_justify(Gtk.Justification.FILL)
- item.connect("activate", self.do_nothing)
- items.append(item)
- menu.append(item)
-
- # sep
- item = Gtk.SeparatorMenuItem()
- menu.append(item)
-
- # about me
- item = Gtk.MenuItem()
- item.set_label("About")
- item.connect("activate", self.show_about)
- menu.append(item)
-
- # add a quit menu item
- item = Gtk.MenuItem()
- item.set_label("Quit")
- item.connect("activate", self.quit)
- menu.append(item)
-
- # set the menu
- menu.show_all()
- ind.set_menu(menu)
- self.menus.append(items)
-
- self.gpus.append(ind)
-
- def add_about_window_contents(self):
- text = Gtk.Label()
- text.set_markup(
- "About NvIndicator\n\n{}\n\n"
- "An NVIDIA GPU indicator applet\n\n"
- ""
- "https://github.com/jeffchannell/nvindicator\n\n"
- ""
- "© 2017 Jeff Channell\n\n"
- "This program comes with absolutely no warranty.\n"
- "See the GNU General Public License, version 3 or later for details."
- "".format(__version__)
- )
- text.set_line_wrap(True)
- text.set_justify(Gtk.Justification.CENTER)
-
- self.about.add(text)
-
- def clear(self):
- for gpu in self.gpus:
- gpu.set_status(appindicator.IndicatorStatus.ACTIVE)
-
- def destroy_about(self, widget, something):
- self.about = None
- return False
-
- def do_nothing(self, widget):
- pass
-
- def main(self):
- self.run_loop()
- Gtk.main()
-
- def quit(self, widget):
- Gtk.main_quit()
-
- def read_nvidia(self):
- result = run(
- ["nvidia-smi", "-q", "-x"],
- stdout=subprocess.PIPE,
- universal_newlines=True
- )
- xml = objectify.fromstring(result.stdout)
- return xml
-
- def run_loop(self):
- xml = self.read_nvidia()
- idx = 0
- for gpu in xml.gpu:
- self.update_gpu(idx, gpu)
- idx = idx + 1
- # end with another loop
- GLib.timeout_add_seconds(1, self.run_loop)
-
- def run_nvidia_settings(self, widget):
- run(["nvidia-settings"])
-
- def show_about(self, widget):
- if None == self.about:
- self.about = Gtk.Window()
- self.about.set_title("About NvInidicator")
- self.about.set_keep_above(True)
- self.about.connect("delete-event", self.destroy_about)
- self.add_about_window_contents()
-
- self.about.set_position(Gtk.WindowPosition.CENTER)
- self.about.set_size_request(400, 200)
- self.about.show_all()
-
-
- def update_gpu(self, idx, gpu):
- self.gpus[idx].set_label(
- "GPU: {}% MEM: {}%".format(
- str(gpu.utilization[0].gpu_util[0]).split()[0].rjust(3),
- str(gpu.utilization[0].memory_util[0]).split()[0].rjust(3)
- ),
- "NvInidicatorUsage"
- )
-
- self.menus[idx][0].set_label(
- "Using {} of {}".format(
- str(gpu.fb_memory_usage[0].used[0]),
- str(gpu.fb_memory_usage[0].total[0])
- )
- )
-
- self.menus[idx][1].set_label(
- "Temperature\t\t{}".format(
- str(gpu.temperature[0].gpu_temp[0])
- )
- )
-
- self.menus[idx][2].set_label(
- "Power Draw\t\t{}".format(
- str(gpu.power_readings[0].power_draw[0])
- )
- )
-
- self.menus[idx][3].set_label(
- "Processes\t\t\t{}".format(
- str(len(gpu.processes))
- )
- )
+ def __init__(self):
+ # check for nvidia app
+ check = run(
+ ["nvidia-smi"],
+ stdout=subprocess.PIPE,
+ universal_newlines=True
+ )
+
+ # about window init
+ self.about = None
+
+ # track menus
+ self.menus = []
+
+ # track gpus
+ self.gpus = []
+ xml = self.read_nvidia()
+
+ # all menus display the driver version
+ driver = str(xml.driver_version[0])
+
+ for gpu in xml.gpu:
+ items = []
+
+ # create a new indicator
+ ind = appindicator.Indicator.new(
+ "NvIndicator",
+ "nvidia-settings",
+ appindicator.IndicatorCategory.HARDWARE
+ )
+ ind.set_status(appindicator.IndicatorStatus.ACTIVE)
+ menu = Gtk.Menu()
+
+ # add an nvidia-settings menu item
+ item = Gtk.MenuItem()
+ item.set_label("Open NVIDIA Settings")
+ item.connect("activate", self.run_nvidia_settings)
+ menu.append(item)
+
+ # sep
+ item = Gtk.SeparatorMenuItem()
+ menu.append(item)
+
+ # gpu name
+ item = Gtk.MenuItem()
+ item.set_label(str(gpu.product_name[0]))
+ item.connect("activate", self.do_nothing)
+ menu.append(item)
+
+ # driver version
+ item = Gtk.MenuItem()
+ item.set_label("Driver\tv{}".format(driver))
+ item.connect("activate", self.do_nothing)
+ menu.append(item)
+
+ # temperature - update 0
+ item = Gtk.MenuItem()
+ item.set_label(
+ "Temperature\t\t{}".format(
+ str(gpu.temperature[0].gpu_temp[0]).strip()
+ )
+ )
+ item.get_children()[0].set_justify(Gtk.Justification.FILL)
+ item.connect("activate", self.do_nothing)
+ items.append(item)
+ menu.append(item)
+
+ # power draw - update 1
+ item = Gtk.MenuItem()
+ item.set_label(
+ "Power Draw\t\t{}".format(
+ str(gpu.power_readings[0].power_draw[0])
+ )
+ )
+ item.get_children()[0].set_justify(Gtk.Justification.FILL)
+ item.connect("activate", self.do_nothing)
+ items.append(item)
+ menu.append(item)
+
+ # processes - update 2
+ item = Gtk.MenuItem()
+ item.set_label(
+ "Processes\t\t\t{}".format(
+ str(len(gpu.processes))
+ )
+ )
+ item.get_children()[0].set_justify(Gtk.Justification.FILL)
+ item.connect("activate", self.do_nothing)
+ items.append(item)
+ menu.append(item)
+
+ # memory usage - update 3
+ item = Gtk.MenuItem()
+ mem_used = str(gpu.fb_memory_usage[0].used[0])
+ mem_total = str(gpu.fb_memory_usage[0].total[0])
+ item.set_label(
+ "MEM Usage: {}M / {}M ({}%)".format(
+ mem_used[:mem_used.index(' ')],
+ mem_total[:mem_total.index(' ')],
+ str(gpu.utilization[0].memory_util[0]).split()[0]
+ )
+ )
+ item.connect("activate", self.do_nothing)
+ items.append(item)
+ menu.append(item)
+
+ # memory usage percent - update 4
+ item = Gtk.MenuItem()
+ item.set_label(
+ "GPU Usage: {}%".format(
+ str(gpu.utilization[0].gpu_util[0]).split()[0].rjust(3)
+ )
+ )
+ item.connect("activate", self.do_nothing)
+ items.append(item)
+ menu.append(item)
+
+ # sep
+ item = Gtk.SeparatorMenuItem()
+ menu.append(item)
+
+ # about me
+ item = Gtk.MenuItem()
+ item.set_label("About")
+ item.connect("activate", self.show_about)
+ menu.append(item)
+
+ # add a quit menu item
+ item = Gtk.MenuItem()
+ item.set_label("Quit")
+ item.connect("activate", self.quit)
+ menu.append(item)
+
+ # set the menu
+ menu.show_all()
+ ind.set_menu(menu)
+ self.menus.append(items)
+
+ self.gpus.append(ind)
+
+ def add_about_window_contents(self):
+ text = Gtk.Label()
+ text.set_markup(
+ "About NvIndicator\n\n{}\n\n"
+ "An NVIDIA GPU indicator applet\n\n"
+ ""
+ "https://github.com/jeffchannell/nvindicator\n\n"
+ ""
+ "© 2017 Jeff Channell\n\n"
+ "This program comes with absolutely no warranty.\n"
+ "See the GNU General Public License, version 3 or later for details."
+ "".format(__version__)
+ )
+ text.set_line_wrap(True)
+ text.set_justify(Gtk.Justification.CENTER)
+
+ self.about.add(text)
+
+ def clear(self):
+ for gpu in self.gpus:
+ gpu.set_status(appindicator.IndicatorStatus.ACTIVE)
+
+ def destroy_about(self, widget, something):
+ self.about = None
+ return False
+
+ def do_nothing(self, widget):
+ pass
+
+ def main(self):
+ self.run_loop()
+ Gtk.main()
+
+ def quit(self, widget):
+ Gtk.main_quit()
+
+ def read_nvidia(self):
+ result = run(
+ ["nvidia-smi", "-q", "-x"],
+ stdout=subprocess.PIPE,
+ universal_newlines=True
+ )
+ xml = objectify.fromstring(result.stdout)
+ return xml
+
+ def run_loop(self):
+ xml = self.read_nvidia()
+ idx = 0
+ for gpu in xml.gpu:
+ self.update_gpu(idx, gpu)
+ idx = idx + 1
+ # end with another loop
+ GLib.timeout_add_seconds(1, self.run_loop)
+
+ def run_nvidia_settings(self, widget):
+ run(["nvidia-settings"])
+
+ def show_about(self, widget):
+ if None == self.about:
+ self.about = Gtk.Window()
+ self.about.set_title("About NvInidicator")
+ self.about.set_keep_above(True)
+ self.about.connect("delete-event", self.destroy_about)
+ self.add_about_window_contents()
+
+ self.about.set_position(Gtk.WindowPosition.CENTER)
+ self.about.set_size_request(400, 200)
+ self.about.show_all()
+
+ def update_gpu(self, idx, gpu):
+ self.gpus[idx].set_label(
+ "{}".format(
+ str(gpu.temperature[0].gpu_temp[0]).strip()
+ ),
+ " "
+ )
+
+ self.menus[idx][0].set_label(
+ "Temperature\t\t{}".format(
+ str(gpu.temperature[0].gpu_temp[0])
+ )
+ )
+
+ self.menus[idx][1].set_label(
+ "Power Draw\t\t{}".format(
+ str(gpu.power_readings[0].power_draw[0])
+ )
+ )
+
+ self.menus[idx][2].set_label(
+ "Processes\t\t\t{}".format(
+ str(len(gpu.processes))
+ )
+ )
+
+ mem_used = str(gpu.fb_memory_usage[0].used[0])
+ mem_total = str(gpu.fb_memory_usage[0].total[0])
+ self.menus[idx][3].set_label(
+ "MEM Usage: {}M / {}M ({}%)".format(
+ mem_used[:mem_used.index(' ')],
+ mem_total[:mem_total.index(' ')],
+ str(gpu.utilization[0].memory_util[0]).split()[0]
+ )
+ )
+
+ self.menus[idx][4].set_label(
+ "GPU Usage: {}%".format(
+ str(gpu.utilization[0].gpu_util[0]).split()[0].rjust(3)
+ )
+ )
+
def main():
- # allow app to be killed using ctrl+c
- signal.signal(signal.SIGINT, signal.SIG_DFL)
- indicator = NvIndicator()
- indicator.main()
+ # allow app to be killed using ctrl+c
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
+ indicator = NvIndicator()
+ indicator.main()
+
if __name__ == '__main__':
- main()
+ main()