]> sigrok.org Git - sigrok-meter.git/blobdiff - sigrok-meter
Temporary fixes for slightly more usable multi-device UI.
[sigrok-meter.git] / sigrok-meter
index 769b36c6a43441e05ffe709bd34b98198617ab74..dc34745445d63f9efc7642726154f73d2d767b65 100755 (executable)
@@ -1,9 +1,9 @@
 #!/usr/bin/env python
-
 ##
 ## This file is part of the sigrok-meter project.
 ##
 ## Copyright (C) 2013 Uwe Hermann <uwe@hermann-uwe.de>
+## Copyright (C) 2014 Jens Steinhauser <jens.steinhauser@gmail.com>
 ##
 ## This program is free software; you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
 ##
 
 import argparse
-from multiprocessing import Process, Queue
-from gi.repository import Gtk, GObject
-import re
 import sigrok.core as sr
 import sys
 import textwrap
 
-default_drivers = [('demo', {'analog_channels': 1})]
-default_loglevel = sr.LogLevel.WARN
-
-def format_unit(u):
-    units = {
-        sr.Unit.VOLT:                   'V',
-        sr.Unit.AMPERE:                 'A',
-        sr.Unit.OHM:                   u'\u03A9',
-        sr.Unit.FARAD:                  'F',
-        sr.Unit.KELVIN:                 'K',
-        sr.Unit.CELSIUS:               u'\u00B0C',
-        sr.Unit.FAHRENHEIT:            u'\u00B0F',
-        sr.Unit.HERTZ:                  'Hz',
-        sr.Unit.PERCENTAGE:             '%',
-      # sr.Unit.BOOLEAN
-        sr.Unit.SECOND:                 's',
-        sr.Unit.SIEMENS:                'S',
-        sr.Unit.DECIBEL_MW:             'dBu',
-        sr.Unit.DECIBEL_VOLT:           'dBV',
-      # sr.Unit.UNITLESS
-        sr.Unit.DECIBEL_SPL:            'dB',
-      # sr.Unit.CONCENTRATION
-        sr.Unit.REVOLUTIONS_PER_MINUTE: 'rpm',
-        sr.Unit.VOLT_AMPERE:            'VA',
-        sr.Unit.WATT:                   'W',
-        sr.Unit.WATT_HOUR:              'Wh',
-        sr.Unit.METER_SECOND:           'm/s',
-        sr.Unit.HECTOPASCAL:            'hPa',
-        sr.Unit.HUMIDITY_293K:          '%rF',
-        sr.Unit.DEGREE:                u'\u00B0',
-        sr.Unit.HENRY:                  'H'
-    }
-
-    return units.get(u, '')
-
-def init_and_run(queue, drivers, loglevel):
-    def datafeed_in(device, packet):
-        if packet.type == sr.PacketType.ANALOG:
-            data = packet.payload.data
-            unit_str = format_unit(packet.payload.unit)
-            mqflags, mqflags_str = packet.payload.mq_flags, ""
-
-            if sr.QuantityFlag.AC in mqflags:
-                mqflags_str = "AC"
-            elif sr.QuantityFlag.DC in mqflags:
-                mqflags_str = "DC"
-
-            for i in range(packet.payload.num_samples):
-                dev = "%s %s" % (device.vendor, device.model)
-                mag_str = "%f" % data[0][i]
-                val = ' '.join([mag_str, unit_str, mqflags_str])
-                queue.put((dev, val))
-
-    context = sr.Context_create()
-    context.log_level = loglevel
-
-    devices = []
-    for name, options in drivers:
-        try:
-            dr = context.drivers[name]
-            devices.append(dr.scan(**options)[0])
-        except:
-            print('error getting device for driver "{}", skipping'.format(name))
-
-    if not devices:
-        print('no devices found')
-        return
-
-    session = context.create_session()
-    for dev in devices:
-        session.add_device(dev)
-        dev.open()
-    session.add_datafeed_callback(datafeed_in)
-    session.start()
-    session.run()
-    session.stop()
-
-class SigrokMeter:
-    def __init__(self):
-        self.builder = Gtk.Builder()
-        self.builder.add_from_file("sigrok-meter.glade")
-        self.builder.connect_signals(self)
-        self.value_label = self.builder.get_object("value_label")
-        self.value_label2 = self.builder.get_object("value_label2")
-        self.win = self.builder.get_object("mainwindow")
-        self.win.show_all()
-        self.queue = Queue()
-        GObject.timeout_add(100, self.update_label_if_needed)
-
-    def update_label_if_needed(self):
-        try:
-            t = self.queue.get_nowait()
-            l = self.value_label if t[0] != "Victor" else self.value_label2
-            l.set_text("%s: %s" % (t[0], t[1]))
-        except:
-            pass
-        GObject.timeout_add(100, self.update_label_if_needed)
-
-    def on_quit(self, *args):
-        Gtk.main_quit(*args)
-
-    def on_about(self, action):
-        about = self.builder.get_object("aboutdialog")
-        context = sr.Context_create()
-        sr_pkg = context.package_version
-        sr_lib = context.lib_version
-        s = "Using libsigrok %s (lib version %s)." % (sr_pkg, sr_lib)
-        about.set_comments(s)
-        about.run()
-        about.hide()
+default_drivers = [('demo:analog_channels=4', 'samplerate=4')]
+default_loglevel = 2
 
 def parse_cli():
     parser = argparse.ArgumentParser(
         description='Simple sigrok GUI for multimeters and dataloggers.',
         epilog=textwrap.dedent('''\
-            The DRIVER string is the same as for sigrok-cli(1).
+            The DRIVER string is the same as for sigrok-cli(1). Multiple
+            DRIVER and CONFIG items can be supplied. The nth CONFIG is applied
+            to the nth DRIVER. If there are more drivers than configs, the
+            remaining drivers use the default configuration.
 
-            examples:
+            Examples:
 
               %(prog)s --driver tecpel-dmm-8061-ser:conn=/dev/ttyUSB0
 
               %(prog)s --driver uni-t-ut61e:conn=1a86.e008
+
+              %(prog)s --driver demo:analog_channels=1 \\
+                       --config samplerate=10
+
+              %(prog)s --driver voltcraft-k204:conn=/dev/ttyUSB0 \\
+                       --driver uni-t-ut61d:conn=1a86.e008 \\
+                       --driver uni-t-ut61e-ser:conn=/dev/ttyUSB1
         '''),
         formatter_class=argparse.RawDescriptionHelpFormatter)
 
     parser.add_argument('-d', '--driver',
         action='append',
+        default=[],
         help='The driver to use')
+    parser.add_argument('-c', '--config',
+        action='append',
+        default=[],
+        help='Specify device configuration options')
     parser.add_argument('-l', '--loglevel',
         type=int,
+        default=default_loglevel,
         help='Set loglevel (5 is most verbose)')
+    parser.add_argument('--pyside',
+        action='store_true',
+        default=False,
+        help='Force use of PySide (default is to use PyQt4)')
     args = parser.parse_args()
 
-    result = {
-        'drivers': default_drivers,
-        'loglevel': default_loglevel
-    }
+    if len(args.config) > len(args.driver):
+        sys.exit('Error: More configurations than drivers given.')
 
+    # Merge drivers and configurations into a list of tuples.
+    setattr(args, 'drivers', [])
+    if not args.driver:
+        args.drivers = default_drivers
+        sys.stderr.write('No driver given, using demo driver.\n')
     if args.driver:
-        result['drivers'] = []
-        for d in args.driver:
-            m = re.match('(?P<name>[^:]+)(?P<opts>(:[^:=]+=[^:=]+)*)', d)
-            if not m:
-                sys.exit('error parsing option "{}"'.format(d))
+        args.config.extend([''] * (len(args.driver) - len(args.config)))
+        args.drivers = zip(args.driver, args.config)
+    del args.driver
+    del args.config
 
-            opts = m.group('opts').split(':')[1:]
-            opts = [tuple(kv.split('=')) for kv in opts]
-            opts = dict(opts)
+    return args
 
-            result['drivers'].append((m.group('name'), opts))
+if __name__ == '__main__':
+    args = parse_cli()
 
-    if args.loglevel != None:
-        try:
-            result['loglevel'] = sr.LogLevel.get(args.loglevel)
-        except:
-            sys.exit('error: invalid log level')
+    import qtcompat
+    qtcompat.load_modules(args.pyside)
+    QtCore = qtcompat.QtCore
+    QtGui = qtcompat.QtGui
+    import mainwindow
 
-    return result
+    context = sr.Context_create()
+    try:
+        loglevel = sr.LogLevel.get(args.loglevel)
+        context.log_level = loglevel
+    except:
+        sys.exit('Error: invalid log level.')
 
-if __name__ == '__main__':
-    args = parse_cli()
-    s = SigrokMeter()
-    process = Process(target=init_and_run,
-            args=(s.queue, args['drivers'], args['loglevel']))
-    process.start()
-    Gtk.main()
-    process.terminate()
+    app = QtGui.QApplication([])
+    s = mainwindow.MainWindow(context, args.drivers)
+    s.show()
 
+    sys.exit(app.exec_())