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())