URI: 
       tqrscanner.py - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
       tqrscanner.py (5178B)
       ---
            1 #!/usr/bin/env python
            2 #
            3 # Electrum - lightweight Bitcoin client
            4 # Copyright (C) 2015 Thomas Voegtlin
            5 #
            6 # Permission is hereby granted, free of charge, to any person
            7 # obtaining a copy of this software and associated documentation files
            8 # (the "Software"), to deal in the Software without restriction,
            9 # including without limitation the rights to use, copy, modify, merge,
           10 # publish, distribute, sublicense, and/or sell copies of the Software,
           11 # and to permit persons to whom the Software is furnished to do so,
           12 # subject to the following conditions:
           13 #
           14 # The above copyright notice and this permission notice shall be
           15 # included in all copies or substantial portions of the Software.
           16 #
           17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
           18 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
           19 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
           20 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
           21 # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
           22 # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
           23 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
           24 # SOFTWARE.
           25 
           26 import os
           27 import sys
           28 import ctypes
           29 
           30 from .util import UserFacingException
           31 from .i18n import _
           32 from .logging import get_logger
           33 
           34 
           35 _logger = get_logger(__name__)
           36 
           37 
           38 if sys.platform == 'darwin':
           39     name = 'libzbar.dylib'
           40 elif sys.platform in ('windows', 'win32'):
           41     name = 'libzbar-0.dll'
           42 else:
           43     name = 'libzbar.so.0'
           44 
           45 try:
           46     libzbar = ctypes.cdll.LoadLibrary(os.path.join(os.path.dirname(__file__), name))
           47 except BaseException as e1:
           48     try:
           49         libzbar = ctypes.cdll.LoadLibrary(name)
           50     except BaseException as e2:
           51         libzbar = None
           52         if sys.platform != 'darwin':
           53             _logger.error(f"failed to load zbar. exceptions: {[e1,e2]!r}")
           54 
           55 
           56 def scan_barcode_ctypes(device='', timeout=-1, display=True, threaded=False):
           57     if libzbar is None:
           58         raise UserFacingException("Cannot start QR scanner: zbar not available.")
           59     libzbar.zbar_symbol_get_data.restype = ctypes.c_char_p
           60     libzbar.zbar_processor_create.restype = ctypes.POINTER(ctypes.c_int)
           61     libzbar.zbar_processor_get_results.restype = ctypes.POINTER(ctypes.c_int)
           62     libzbar.zbar_symbol_set_first_symbol.restype = ctypes.POINTER(ctypes.c_int)
           63     # libzbar.zbar_set_verbosity(100)  # verbose logs for debugging
           64     proc = libzbar.zbar_processor_create(threaded)
           65     libzbar.zbar_processor_request_size(proc, 640, 480)
           66     if libzbar.zbar_processor_init(proc, device.encode('utf-8'), display) != 0:
           67         raise UserFacingException(
           68             _("Cannot start QR scanner: initialization failed.") + "\n" +
           69             _("Make sure you have a camera connected and enabled."))
           70     libzbar.zbar_processor_set_visible(proc)
           71     if libzbar.zbar_process_one(proc, timeout):
           72         symbols = libzbar.zbar_processor_get_results(proc)
           73     else:
           74         symbols = None
           75     libzbar.zbar_processor_destroy(proc)
           76     if symbols is None:
           77         return
           78     if not libzbar.zbar_symbol_set_get_size(symbols):
           79         return
           80     symbol = libzbar.zbar_symbol_set_first_symbol(symbols)
           81     data = libzbar.zbar_symbol_get_data(symbol)
           82     return data.decode('utf8')
           83 
           84 def scan_barcode_osx(*args_ignored, **kwargs_ignored):
           85     import subprocess
           86     # NOTE: This code needs to be modified if the positions of this file changes with respect to the helper app!
           87     # This assumes the built macOS .app bundle which ends up putting the helper app in
           88     # .app/contrib/osx/CalinsQRReader/build/Release/CalinsQRReader.app.
           89     root_ec_dir = os.path.abspath(os.path.dirname(__file__) + "/../")
           90     prog = root_ec_dir + "/" + "contrib/osx/CalinsQRReader/build/Release/CalinsQRReader.app/Contents/MacOS/CalinsQRReader"
           91     if not os.path.exists(prog):
           92         raise UserFacingException("Cannot start QR scanner: helper app not found.")
           93     data = ''
           94     try:
           95         # This will run the "CalinsQRReader" helper app (which also gets bundled with the built .app)
           96         # Just like the zbar implementation -- the main app will hang until the QR window returns a QR code
           97         # (or is closed). Communication with the subprocess is done via stdout.
           98         # See contrib/CalinsQRReader for the helper app source code.
           99         with subprocess.Popen([prog], stdout=subprocess.PIPE) as p:
          100             data = p.stdout.read().decode('utf-8').strip()
          101         return data
          102     except OSError as e:
          103         raise UserFacingException("Cannot start camera helper app: {}".format(e.strerror))
          104 
          105 scan_barcode = scan_barcode_osx if sys.platform == 'darwin' else scan_barcode_ctypes
          106 
          107 def _find_system_cameras():
          108     device_root = "/sys/class/video4linux"
          109     devices = {} # Name -> device
          110     if os.path.exists(device_root):
          111         for device in os.listdir(device_root):
          112             path = os.path.join(device_root, device, 'name')
          113             try:
          114                 with open(path, encoding='utf-8') as f:
          115                     name = f.read()
          116             except Exception:
          117                 continue
          118             name = name.strip('\n')
          119             devices[name] = os.path.join("/dev", device)
          120     return devices
          121 
          122 
          123 if __name__ == "__main__":
          124     print(scan_barcode())