def __init__(self, filename, loop=False): self._filename = filename self._is_playing = False self._lib = _lib self._lib_version = _lib_version self._loop = loop self._play_timestamp = 0 self._play_count = 0 self._thread = -1 if not _initialized: self._server = init() else: self._server = _server if _initialized and not isinstance(_initialized, Exception): if not self._lib and _lib: self._lib = _lib self._lib_version = _lib_version if not self._snd and self._filename: if self._lib == "pyo": self._snd = pyo.SfPlayer(safe_str(self._filename), loop=self._loop) elif self._lib == "pyglet": snd = pyglet.media.load(self._filename, streaming=False) self._ch = pyglet.media.Player() self._snd = snd elif self._lib == "SDL": rw = sdl.SDL_RWFromFile(safe_str(self._filename, "UTF-8"), "rb") self._snd = self._server.Mix_LoadWAV_RW(rw, 1) elif self._lib == "wx": self._snd = wx.Sound(self._filename)
def _schtasks(self, args, elevated=False, echo=False): if elevated: try: p = run_as_admin("schtasks.exe", args, close_process=False, show=False) except pywintypes.error as exception: if exception.args[0] == winerror.ERROR_CANCELLED: self.lastreturncode = winerror.ERROR_CANCELLED else: raise else: self.lastreturncode = int(p["hProcess"].handle == 0) p["hProcess"].Close() finally: self.stdout = "" else: args.insert(0, "schtasks.exe") startupinfo = sp.STARTUPINFO() startupinfo.dwFlags |= sp.STARTF_USESHOWWINDOW startupinfo.wShowWindow = sp.SW_HIDE p = sp.Popen([safe_str(arg) for arg in args], stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.STDOUT, startupinfo=startupinfo) self.stdout, stderr = p.communicate() if echo: safe_print(safe_unicode(self.stdout, enc)) self.lastreturncode = p.returncode return self.lastreturncode == 0
def find(what, search): """ Find device or profile and return object path """ if not isinstance(Colord, DBusObject): raise CDError("colord API not available") if not isinstance(search, list): search = [search] method_name = "_".join(part for part in what.split("-")) try: return getattr(Colord, "find_" + method_name)(*search) except Exception as exception: if hasattr(exception, "get_dbus_name"): if exception.get_dbus_name( ) == "org.freedesktop.ColorManager.NotFound": raise CDObjectNotFoundError(safe_str(exception)) else: raise CDObjectQueryError(safe_str(exception)) raise CDError(safe_str(exception))
def __init__(self, object_path, object_type): try: DBusObject.__init__(self, BUSTYPE_SYSTEM, "org.freedesktop.ColorManager", object_path, object_type) except DBusException as exception: raise CDError(safe_str(exception)) self._object_type = object_type
def __init__(self, filename, logdir, when="never", backupCount=0): self.filename = filename self._logger = get_file_logger(md5(safe_str(filename, "UTF-8")).hexdigest(), when=when, backupCount=backupCount, logdir=logdir, filename=filename)
def properties(self): try: properties = {} for key, value in self._properties.items(): if key == "Profiles": value = [Profile(object_path) for object_path in value] properties[key] = value return properties except DBusException as exception: raise CDError(safe_str(exception))
def device_id_from_edid(edid, quirk=False, use_serial_32=True, truncate_edid_strings=False, omit_manufacturer=False, query=False): """ Assemble device key from EDID """ # https://github.com/hughsie/colord/blob/master/doc/device-and-profile-naming-spec.txt # Should match device ID returned by gcm_session_get_output_id in # gnome-settings-daemon/plugins/color/gsd-color-state.c # and Edid::deviceId in colord-kde/colord-kded/Edid.cpp respectively if "hash" in edid: device_id = device_ids.get(edid["hash"]) if device_id: return device_id elif (sys.platform not in ("darwin", "win32") and query and isinstance(Colord, DBusObject)): try: device = Device( find("device-by-property", ["OutputEdidMd5", edid["hash"]])) device_id = device.properties.get("DeviceId") except CDError as exception: warnings.warn(safe_str(exception), Warning) else: if device_id: device_ids[edid["hash"]] = device_id return device_id parts = ["xrandr"] edid_keys = ["monitor_name", "serial_ascii"] if not omit_manufacturer: edid_keys.insert(0, "manufacturer") if use_serial_32: edid_keys.append("serial_32") for name in edid_keys: value = edid.get(name) if value: if name == "serial_32" and "serial_ascii" in edid: # Only add numeric serial if no ascii serial continue elif name == "manufacturer": if quirk: value = quirk_manufacturer(value) elif isinstance(value, str) and truncate_edid_strings: # Older versions of colord used only the first 12 bytes value = value[:12] parts.append(str(value)) if len(parts) > 1: device_id = "-".join(parts) return device_id
def _unquote(self, token, do_unescape=True, check=False, fileobj=None, lineno=-1): if len(token) > 1: c = token[0] if c in "'"'"' and c == token[-1]: token = token[1:-1] if check and token.count(c) != token.count("\\" + c): raise ValueError("Unescaped quotes found in token " "(%r line %i)" % (safe_str(getattr(fileobj, "name", token)), lineno)) if do_unescape: token = unescape(token) elif check and (token.count('"') != token.count('\\"')): raise ValueError("Unbalanced quotes found in token " "(%r line %i)" % (safe_str(getattr(fileobj, "name", token)), lineno)) if check and "\\'" in token: raise ValueError("Found unknown escape character \"'\" " "(%r line %i)" % (safe_str(getattr(fileobj, "name", token)), lineno)) return token
def OnClose(self, event): # So we can send_command('close') ourselves without prematurely exiting # the wx main loop while self.busy: wx.Yield() sleep(.05) # Hide first (looks nicer) self.Hide() try: with open(self.historyfilename, "wb") as historyfile: for command in self.history: if command: historyfile.write( safe_str(command, "UTF-8") + os.linesep) except EnvironmentError as exception: safe_print("Warning - couldn't write history file:", exception) self.listening = False # Need to use CallAfter to prevent hang under Windows if minimized wx.CallAfter(self.Destroy)
def create_tempdir(self): """ Create a temporary working directory and return its path. """ if not self.tempdir or not os.path.isdir(self.tempdir): # we create the tempdir once each calibrating/profiling run # (deleted by 'wrapup' after each run) if verbose >= 2: if not self.tempdir: msg = "there is none" else: msg = "the previous (%s) no longer exists" % self.tempdir safe_print( appname + ": Creating a new temporary directory " "because", msg) try: self.tempdir = tempfile.mkdtemp(prefix=appname + "-") except Exception as exception: self.tempdir = None return Error("Error - couldn't create temporary directory: " + safe_str(exception)) return self.tempdir
def get_default_profile(device_id): """ Get default profile for device """ # Find device object path device = Device(get_object_path(device_id, "device")) # Get default profile try: properties = device.properties except Exception as exception: raise CDError(safe_str(exception)) else: if properties.get("ProfilingInhibitors"): return None profiles = properties.get("Profiles") if profiles: return profiles[0] else: raise CDError("Couldn't get default profile for device ID %r" % device_id)
def _main(module, name, applockfilename, probe_ports=True): # Allow multiple instances only for curve viewer, profile info, # scripting client, synthetic profile creator and testchart editor multi_instance = ("curve-viewer", "profile-info", "scripting-client", "synthprofile", "testchart-editor") lock = AppLock(applockfilename, "a+", True, module in multi_instance) if not lock: # If a race condition occurs, do not start another instance safe_print("Not starting another instance.") return log("=" * 80) if verbose >= 1: version = VERSION_STRING if VERSION > VERSION_BASE: version += " Beta" safe_print(pyname + runtype, version, build) if sys.platform == "darwin": # Python's platform.platform output is useless under Mac OS X # (e.g. 'Darwin-15.0.0-x86_64-i386-64bit' for Mac OS X 10.11 El Capitan) safe_print("Mac OS X %s %s" % (mac_ver()[0], mac_ver()[-1])) elif sys.platform == "win32": machine = platform.machine() safe_print(*[v for v in win_ver() if v] + ({ "AMD64": "x86_64" }.get(machine, machine), )) else: # Linux safe_print(' '.join(platform.dist()), platform.machine()) safe_print("Python " + sys.version) cafile = os.getenv("SSL_CERT_FILE") if cafile: safe_print("CA file", cafile) # Enable faulthandler try: import faulthandler except Exception as exception: safe_print(exception) else: try: faulthandler.enable( open(os.path.join(logdir, pyname + "-fault.log"), "w")) except Exception as exception: safe_print(exception) else: safe_print("Faulthandler", getattr(faulthandler, "__version__", "")) from wxaddons import wx if "phoenix" in wx.PlatformInfo: # py2exe helper so wx.xml gets picked up from wx import xml safe_print("wxPython " + wx.version()) safe_print("Encoding: " + enc) safe_print("File system encoding: " + fs_enc) if sys.platform == "win32" and sys.getwindowsversion() >= (6, 2): # HighDPI support try: shcore = ctypes.windll.shcore except Exception as exception: safe_print("Warning - could not load shcore:", exception) else: if hasattr(shcore, "SetProcessDpiAwareness"): try: # 1 = System DPI aware (wxWpython currently does not # support per-monitor DPI) shcore.SetProcessDpiAwareness(1) except Exception as exception: safe_print("Warning - SetProcessDpiAwareness() failed:", exception) else: safe_print( "Warning - SetProcessDpiAwareness not found in shcore") initcfg(module) host = "127.0.0.1" defaultport = getcfg("app.port") lock2pids_ports = {} opid = os.getpid() if probe_ports: # Check for currently used ports lockfilenames = glob.glob(os.path.join(confighome, "*.lock")) for lockfilename in lockfilenames: safe_print("Lockfile", lockfilename) try: if lock and lockfilename == applockfilename: lockfile = lock lock.seek(0) else: lockfile = AppLock(lockfilename, "r", True, True) if lockfile: if not lockfilename in lock2pids_ports: lock2pids_ports[lockfilename] = [] for ln, line in enumerate(lockfile.read().splitlines(), 1): if ":" in line: # DisplayCAL >= 3.8.8.2 with localhost blocked pid, port = line.split(":", 1) if pid: try: pid = int(pid) except ValueError as exception: # This shouldn't happen safe_print("Warning - couldn't parse PID " "as int: %r (%s line %i)" % (pid, lockfilename, ln)) pid = None else: safe_print("Existing client using PID", pid) else: # DisplayCAL <= 3.8.8.1 or localhost ok pid = None port = line if port: try: port = int(port) except ValueError as exception: # This shouldn't happen safe_print( "Warning - couldn't parse port as int: %r " "(%s line %i)" % (port, lockfilename, ln)) port = None else: safe_print("Existing client using port", port) if pid or port: lock2pids_ports[lockfilename].append((pid, port)) if not lock or lockfilename != applockfilename: lockfile.unlock() except EnvironmentError as exception: # This shouldn't happen safe_print( "Warning - could not read lockfile %s:" % lockfilename, exception) if module not in multi_instance: # Check lockfile(s) and probe port(s) for lockfilename in [applockfilename]: incoming = None pids_ports = lock2pids_ports.get(lockfilename) if pids_ports: pid, port = pids_ports[0] appsocket = AppSocket() if appsocket and port: safe_print("Connecting to %s..." % port) if appsocket.connect(host, port): safe_print("Connected to", port) # Other instance already running? # Get appname to check if expected app is actually # running under that port safe_print("Getting instance name") if appsocket.send("getappname"): safe_print( "Sent scripting request, awaiting response..." ) incoming = appsocket.read().rstrip("\4") safe_print("Got response: %r" % incoming) if incoming: if incoming != pyname: incoming = None else: incoming = False while incoming: # Send args as UTF-8 if module == "apply-profiles": # Always try to close currently running instance safe_print("Closing existing instance") cmd = "exit" if incoming == pyname else "close" data = [cmd] lock.unlock() else: # Send module/appname to notify running app safe_print("Notifying existing instance") data = [module or appname] if module != "3DLUT-maker": for arg in sys.argv[1:]: data.append( safe_str(safe_unicode(arg), "UTF-8")) data = sp.list2cmdline(data) if appsocket.send(data): safe_print( "Sent scripting request, awaiting response..." ) incoming = appsocket.read().rstrip("\4") safe_print("Got response: %r" % incoming) if module == "apply-profiles": if incoming == "": # Successfully sent our close request. incoming = "ok" elif incoming == "invalid" and cmd == "exit": # < 3.8.8.1 didn't have exit command continue break appsocket.close() else: pid = None if not incoming: if sys.platform == "win32": import pywintypes import win32ts try: osid = win32ts.ProcessIdToSessionId(opid) except pywintypes.error as exception: safe_print("Enumerating processes failed:", exception) osid = None try: processes = win32ts.WTSEnumerateProcesses() except pywintypes.error as exception: safe_print("Enumerating processes failed:", exception) else: appname_lower = appname.lower() exename_lower = exename.lower() if module: pyexe_lower = appname_lower + "-" + module + exe_ext else: pyexe_lower = appname_lower + exe_ext incoming = None for (sid, pid2, basename, usid) in processes: basename_lower = basename.lower() if ((pid and pid2 == pid and basename_lower == exename_lower) or ((osid is None or sid == osid) and basename_lower == pyexe_lower)) and pid2 != opid: # Other instance running incoming = False if module == "apply-profiles": if not os.path.isfile(lockfilename): # Create dummy lockfile try: with open(lockfilename, "w"): pass except EnvironmentError as exception: safe_print( "Warning - could " "not create dummy " "lockfile %s: %r" % (lockfilename, exception)) else: safe_print( "Warning - had to " "create dummy " "lockfile", lockfilename) safe_print( "Closing existing instance " "with PID", pid2) startupinfo = sp.STARTUPINFO() startupinfo.dwFlags |= sp.STARTF_USESHOWWINDOW startupinfo.wShowWindow = sp.SW_HIDE lock.unlock() try: p = sp.Popen( [ "taskkill", "/PID", "%s" % pid2 ], stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.STDOUT, startupinfo=startupinfo) stdout, stderr = p.communicate() except Exception as exception: safe_print(exception) else: safe_print(stdout) if not p.returncode: # Successfully sent our close # request. incoming = "ok" if incoming == "ok": # Successfully sent our request if module == "apply-profiles": # Wait for lockfile to be removed, in which case # we know the running instance has successfully # closed. safe_print( "Waiting for existing instance to exit and " "delete lockfile", lockfilename) while os.path.isfile(lockfilename): sleep(.05) lock.lock() safe_print("Existing instance exited.") incoming = None if lockfilename in lock2pids_ports: del lock2pids_ports[lockfilename] break if incoming is not None: # Other instance running? import localization as lang lang.init() if incoming == "ok": # Successfully sent our request safe_print(lang.getstr("app.otherinstance.notified")) elif module == "apply-profiles": safe_print("Not starting another instance.") else: # Other instance busy? handle_error(lang.getstr("app.otherinstance", name)) # Exit return # Use exclusive lock during app startup with lock: # Create listening socket appsocket = AppSocket() if appsocket: if sys.platform != "win32": # https://docs.microsoft.com/de-de/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse#using-so_reuseaddr # From the above link: "The SO_REUSEADDR socket option allows # a socket to forcibly bind to a port in use by another socket". # Note that this is different from the behavior under Linux/BSD, # where a socket can only be (re-)bound if no active listening # socket is already bound to the address. # Consequently, we don't use SO_REUSEADDR under Windows. appsocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sys._appsocket = appsocket.socket if getcfg("app.allow_network_clients"): host = "" used_ports = [ pid_port[1] for pids_ports in list(lock2pids_ports.values()) for pid_port in pids_ports ] candidate_ports = [0] if not defaultport in used_ports: candidate_ports.insert(0, defaultport) for port in candidate_ports: try: sys._appsocket.bind((host, port)) except socket.error as exception: if port == 0: safe_print( "Warning - could not bind to %s:%s:" % (host, port), exception) del sys._appsocket break else: try: sys._appsocket.settimeout(.2) except socket.error as exception: safe_print( "Warning - could not set socket " "timeout:", exception) del sys._appsocket break try: sys._appsocket.listen(1) except socket.error as exception: safe_print("Warning - could not listen on " "socket:", exception) del sys._appsocket break try: port = sys._appsocket.getsockname()[1] except socket.error as exception: safe_print( "Warning - could not get socket " "address:", exception) del sys._appsocket break sys._appsocket_port = port break if not hasattr(sys, "_appsocket_port"): port = "" lock.seek(0) if module not in multi_instance: lock.truncate(0) if not port: lock.write("%s:%s" % (opid, port)) else: lock.write(port) atexit.register(lambda: safe_print("Ran application exit handlers")) from wxwindows import BaseApp BaseApp.register_exitfunc(_exit, applockfilename, port) # Check for required resource files mod2res = { "3DLUT-maker": ["xrc/3dlut.xrc"], "curve-viewer": [], "profile-info": [], "scripting-client": [], "synthprofile": ["xrc/synthicc.xrc"], "testchart-editor": [], "VRML-to-X3D-converter": [] } for filename in mod2res.get(module, resfiles): path = get_data_path(os.path.sep.join(filename.split("/"))) if not path or not os.path.isfile(path): import localization as lang lang.init() raise ResourceError( lang.getstr("resources.notfound.error") + "\n" + filename) # Create main data dir if it does not exist if not os.path.exists(datahome): try: os.makedirs(datahome) except Exception as exception: handle_error( UserWarning("Warning - could not create " "directory '%s'" % datahome)) elif sys.platform == "darwin": # Check & fix permissions if necessary import getpass user = getpass.getuser().decode(fs_enc) script = [] for directory in (confighome, datahome, logdir): if (os.path.isdir(directory) and not os.access(directory, os.W_OK)): script.append("chown -R '%s' '%s'" % (user, directory)) if script: sp.call([ 'osascript', '-e', 'do shell script "%s" with administrator privileges' % ";".join(script).encode(fs_enc) ]) # Initialize & run if module == "3DLUT-maker": from wxLUT3DFrame import main elif module == "curve-viewer": from wxLUTViewer import main elif module == "profile-info": from wxProfileInfo import main elif module == "scripting-client": from wxScriptingClient import main elif module == "synthprofile": from wxSynthICCFrame import main elif module == "testchart-editor": from wxTestchartEditor import main elif module == "VRML-to-X3D-converter": from wxVRML2X3D import main elif module == "apply-profiles": from profile_loader import main else: from DisplayCAL import main # Run main after releasing lock main()
from util_os import getenvu, relpath, safe_glob from util_str import safe_str appname = name bits = platform.architecture()[0][:2] pypath = os.path.abspath(__file__) pydir = os.path.dirname(pypath) basedir = os.path.dirname(pydir) if sys.platform in ("darwin", "win32"): # Adjust PATH so ctypes.util.find_library can find SDL2 DLLs (if present) pth = getenvu("PATH") libpth = os.path.join(pydir, "lib") if not pth.startswith(libpth + os.pathsep): pth = libpth + os.pathsep + pth os.environ["PATH"] = safe_str(pth) config = {"data": ["tests/*.icc"], "doc": ["CHANGES.html", "LICENSE.txt", "README.html", "README-fr.html", "screenshots/*.png", "theme/*.png", "theme/*.css", "theme/*.js", "theme/*.svg", "theme/icons/favicon.ico", "theme/slimbox2/*.css", "theme/slimbox2/*.js"], # Excludes for .app/.exe builds
def parse(self, fileobj): """ Parse fileobj and update dict """ style = None value = [] block_styles = ("|", ">", "|-", ">-", "|+", ">+") quote = None key = None # Readlines is actually MUCH faster than iterating over the # file object for i, line in enumerate(fileobj.readlines(), 1): line = line.replace("\r\n", "\n") line_lwstrip = line.lstrip(" ") if quote: line_rstrip = line.rstrip() if self.debug: print('LINE', repr(line)) if not quote and style not in block_styles and line_lwstrip.startswith("#"): # Ignore comments pass elif quote and line_rstrip and line_rstrip[-1] == quote: if self.debug: print("END QUOTE") if self.debug: print("+ APPEND STRIPPED", repr(line.strip())) value.append(line.strip()) self._collect(key, value, ">i") style = None value = [] quote = None key = None elif (style not in block_styles and line.startswith(" ") and line_lwstrip and line_lwstrip[0] in ("'", '"')): if quote: raise ValueError("Wrong end quote while scanning quoted " "scalar (%r line %i)" % (safe_str(getattr(fileobj, "name", line)), i)) else: if self.debug: print("START QUOTE") quote = line_lwstrip[0] if self.debug: print("+ APPEND LWSTRIPPED", repr(line_lwstrip)) value.append(line_lwstrip) elif line.startswith(" ") and (style in block_styles or line_lwstrip != "\n"): if style == ">i": if not quote and "\t" in line: raise ValueError("Found character '\\t' that cannot " "start any token (%r line %i)" % (safe_str(getattr(fileobj, "name", line)), i)) line = line.strip() + "\n" if self.debug: print("APPEND STRIPPED + \\n", repr(line)) else: line = line[2:] if self.debug: print("APPEND [2:]", repr(line)) value.append(line) elif not quote and line_lwstrip != "\n" and not line.startswith(" "): if key and value: self._collect(key, value, style) tokens = line.split(":", 1) key = unquote(tokens[0].strip()) if len(tokens) > 1: token = tokens[1].lstrip(" ").rstrip(" \n") if token.startswith("|") or token.startswith(">"): if token[1:2] in "+-": style = token[:2] token = token[2:].lstrip(" ") else: style = token[:1] token = token[1:].lstrip(" ") else: style = "" if token.startswith("\t"): raise ValueError("Found character '\\t' that cannot " "start any token (%r line %i)" % (safe_str(getattr(fileobj, "name", line)), i)) if style.startswith(">"): raise NotImplementedError("Folded style is not " "supported (%r line %i)" % (safe_str(getattr(fileobj, "name", line)), i)) if token.startswith("#"): # Block or folded if self.debug: print('IN BLOCK', repr(key), style) value = [] continue if style and token: raise ValueError("Expected a comment or a line break " "(%r line %i)" % (safe_str(getattr(fileobj, "name", line)), i)) else: raise ValueError("Unsupported format (%r line %i)" % (safe_str(getattr(fileobj, "name", line)), i)) if style or not token: # Block or folded if self.debug: print('IN BLOCK', repr(key), style) value = [] else: # Inline value if self.debug: print('IN PLAIN', repr(key), repr(token)) style = None if token.startswith("#"): value = [] continue token_rstrip = token.rstrip() if (token_rstrip and token_rstrip[0] in ("'", '"') and (len(token_rstrip) < 2 or token_rstrip[0] != token_rstrip[-1])): if self.debug: print("START QUOTE") quote = token_rstrip[0] else: style = ">i" comment_offset = token_rstrip.find("#") if (comment_offset > -1 and token_rstrip[comment_offset - 1:comment_offset] == " "): token_rstrip = token_rstrip[:comment_offset].rstrip() token_rstrip += "\n" if self.debug: print("SET", repr(token_rstrip)) value = [token_rstrip] else: #if line_lwstrip == "\n": if True: if self.debug: print("APPEND LWSTRIPPED", repr(line_lwstrip)) line = line_lwstrip else: if self.debug: print("APPEND", repr(line)) value.append(line) if quote: raise ValueError("EOF while scanning quoted scalar (%r line %i)" % (safe_str(getattr(fileobj, "name", line)), i)) if key: if self.debug: print("FINAL COLLECT") self._collect(key, value, style)
def parse(self, fileobj): """ Parse fileobj and update dict """ block = False value = [] key = None # Readlines is actually MUCH faster than iterating over the # file object for i, line in enumerate(fileobj.readlines(), 1): line = line.replace("\r\n", "\n") if line.lstrip(" ").startswith("#"): # Ignore comments pass elif line != "\n" and not line.startswith(" "): if value: self[key] = "".join(value).rstrip("\n") #tokens = line.rstrip(' -|\n').split(":", 1) tokens = line.split(":", 1) if len(tokens) == 1: raise ValueError("Unsupported format (%r line %i)" % (safe_str(getattr(fileobj, "name", line)), i)) # key = tokens[0].strip("'"'"') key = self._unquote(tokens[0].strip(), False, False, fileobj, i) token = tokens[1].strip(" \n") if token.startswith("|-"): block = True token = token[2:].lstrip(" ") if token: if token.startswith("#"): value = [] continue raise ValueError("Expected a comment or a line break " "(%r line %i)" % (safe_str(getattr(fileobj, "name", line)), i)) elif token.startswith("|") or token.startswith(">"): raise ValueError("Style not supported " "(%r line %i)" % (safe_str(getattr(fileobj, "name", line)), i)) elif token.startswith("\t"): raise ValueError("Found character '\\t' that cannot " "start any token (%r line %i)" % (safe_str(getattr(fileobj, "name", line)), i)) if token: # Inline value block = False if token.startswith("#"): value = [] continue comment_offset = token.find("#") if (comment_offset > -1 and token[comment_offset - 1:comment_offset] == " "): token = token[:comment_offset].rstrip(" \n") if not token: value = [] continue # value = [token.strip("'"'"')] value = [self._unquote(token, True, True, fileobj, i)] else: value = [] else: if not block: raise ValueError("Unsupported format (%r line %i)" % (safe_str(getattr(fileobj, "name", line)), i)) value.append(line[2:]) if key: self[key] = "".join(value).rstrip("\n")
def __init__(self, profile, intent="r", direction="f", order="n", pcs=None, scale=1, cwd=None, startupinfo=None, use_icclu=False, use_cam_clipping=False, logfile=None, worker=None, show_actual_if_clipped=False, input_encoding=None, output_encoding=None, convert_video_rgb_to_clut65=False, verbose=1): if not profile: raise Error("Xicclu: Profile is %r" % profile) WorkerBase.__init__(self) self.scale = scale self.convert_video_rgb_to_clut65 = convert_video_rgb_to_clut65 self.logfile = logfile self.worker = worker self.temp = False utilname = "icclu" if use_icclu else "xicclu" xicclu = get_argyll_util(utilname) if not xicclu: raise Error(lang.getstr("argyll.util.not_found", utilname)) if not isinstance(profile, (CGATS.CGATS, ICCP.ICCProfile)): if profile.lower().endswith(".cal"): profile = CGATS.CGATS(profile) else: profile = ICCP.ICCProfile(profile) is_profile = isinstance(profile, ICCP.ICCProfile) if (is_profile and profile.version >= 4 and not profile.convert_iccv4_tags_to_iccv2()): raise Error("\n".join([ lang.getstr("profile.iccv4.unsupported"), profile.getDescription() ])) if not profile.fileName or not os.path.isfile(profile.fileName): if profile.fileName: prefix = os.path.basename(profile.fileName) elif is_profile: prefix = make_filename_safe(profile.getDescription(), concat=False) + profile_ext else: # CGATS (.cal) prefix = "cal" prefix += "-" if not cwd: cwd = self.create_tempdir() if isinstance(cwd, Exception): raise cwd fd, profile.fileName = tempfile.mkstemp("", prefix, dir=cwd) stream = os.fdopen(fd, "wb") profile.write(stream) stream.close() self.temp = True elif not cwd: cwd = os.path.dirname(profile.fileName) profile_basename = safe_unicode(os.path.basename(profile.fileName)) profile_path = profile.fileName if sys.platform == "win32": profile_path = win32api.GetShortPathName(profile_path) self.profile_path = safe_str(profile_path) if sys.platform == "win32" and not startupinfo: startupinfo = sp.STARTUPINFO() startupinfo.dwFlags |= sp.STARTF_USESHOWWINDOW startupinfo.wShowWindow = sp.SW_HIDE xicclu = safe_str(xicclu) cwd = safe_str(cwd) self.verbose = verbose args = [xicclu, "-v%i" % verbose, "-s%s" % scale] self.show_actual_if_clipped = False if utilname == "xicclu": if (is_profile and show_actual_if_clipped and "A2B0" in profile.tags and ("B2A0" in profile.tags or direction == "if")): args.append("-a") self.show_actual_if_clipped = True if use_cam_clipping: args.append("-b") if get_argyll_version("xicclu") >= [1, 6]: # Add encoding parameters # Note: Not adding -e -E can cause problems due to unitialized # in_tvenc and out_tvenc variables in xicclu.c for Argyll 1.6.x if not input_encoding: input_encoding = "n" if not output_encoding: output_encoding = "n" args += [ "-e" + safe_str(input_encoding), "-E" + safe_str(output_encoding) ] args.append("-f" + direction) self.output_scale = 1.0 if is_profile: if profile.profileClass not in ("abst", "link"): args.append("-i" + intent) if order != "n": args.append("-o" + order) if profile.profileClass != "link": if (direction in ("f", "ib") and (pcs == "x" or (profile.connectionColorSpace == "XYZ" and not pcs))): # In case of forward lookup with XYZ PCS, use 0..100 scaling # internally so we get extra precision from xicclu for the # decimal part. Scale back to 0..1 later. pcs = "X" self.output_scale = 100.0 if pcs: args.append("-p" + pcs) args.append(self.profile_path) if debug or verbose > 1: self.sessionlogfile = LogFile(profile_basename + ".xicclu", os.path.dirname(profile.fileName)) if is_profile: profile_act = ICCP.ICCProfile(profile.fileName) self.sessionlogfile.write( "Profile ID %s (actual %s)" % (hexlify( profile.ID), hexlify(profile_act.calculateID(False)))) if cwd: self.log(lang.getstr("working_dir")) indent = " " for name in cwd.split(os.path.sep): self.log( textwrap.fill(name + os.path.sep, 80, expand_tabs=False, replace_whitespace=False, initial_indent=indent, subsequent_indent=indent)) indent += " " self.log("") self.log(lang.getstr("commandline")) printcmdline(xicclu, args[1:], fn=self.log, cwd=cwd) self.log("") self.startupinfo = startupinfo self.args = args self.cwd = cwd self.spawn()
def install_profile(device_id, profile, timeout=CD_CLIENT_IMPORT_DAEMON_TIMEOUT / 1000.0, logfn=None): """ Install profile for device timeout Time to allow for colord to pick up new profiles (recommended not below 2 secs) """ profile_installname = os.path.join(xdg_data_home, 'icc', os.path.basename(profile.fileName)) profile_exists = os.path.isfile(profile_installname) if (profile.fileName != profile_installname and profile_exists): if logfn: logfn("About to overwrite existing", profile_installname) profile.fileName = None if profile.ID == "\0" * 16: profile.calculateID() profile.fileName = None profile_id = "icc-" + hexlify(profile.ID) # Write profile to destination profile_installdir = os.path.dirname(profile_installname) if not os.path.isdir(profile_installdir): os.makedirs(profile_installdir) # colormgr seems to have a bug where the first attempt at importing a # specific profile can time out. This seems to be work-aroundable by # writing the profile ourself first, and then importing. if not profile.fileName or not profile_exists: if logfn: logfn("Writing", profile_installname) profile.fileName = profile_installname profile.write() cdprofile = None if Colord and not isinstance(Colord, DBusObject): client = client_connect() else: # Query colord for profile try: cdprofile = get_object_path(profile_id, "profile") except CDObjectQueryError as exception: # Profile not found pass colormgr = which("colormgr") if not colormgr: raise CDError("colormgr helper program not found") from worker import printcmdline cmd = safe_str(colormgr) if not cdprofile: # Import profile if logfn: logfn("-" * 80) logfn(lang.getstr("commandline")) args = [cmd, "import-profile", safe_str(profile.fileName)] printcmdline(args[0], args[1:], fn=logfn) if logfn: logfn("") ts = time.time() maxtries = 3 for n in range(1, maxtries + 1): if logfn: logfn("Trying to import profile, attempt %i..." % n) try: p = sp.Popen(args, stdout=sp.PIPE, stderr=sp.STDOUT) stdout, stderr = p.communicate() except Exception as exception: raise CDError(safe_str(exception)) if logfn and stdout.strip(): logfn(stdout.strip()) if p.returncode == 0 or os.path.isfile(profile_installname): if logfn: logfn("...ok") break elif logfn: logfn("...failed!") if p.returncode != 0 and not os.path.isfile(profile_installname): raise CDTimeout("Trying to import profile '%s' failed after " "%i tries." % (profile.fileName, n)) if not cdprofile: # Query colord for newly added profile for i in range(int(timeout / 1.0)): try: if Colord and not isinstance(Colord, DBusObject): cdprofile = client.find_profile_sync( profile_id, cancellable) else: cdprofile = get_object_path(profile_id, "profile") except CDObjectQueryError as exception: # Profile not found pass if cdprofile: break # Give colord time to pick up the profile sleep(1) if not cdprofile: raise CDTimeout( "Querying for profile %r returned no result for %s " "secs" % (profile_id, timeout)) errmsg = "Could not make profile %s default for device %s" % (profile_id, device_id) if Colord and not isinstance(Colord, DBusObject): # Connect to profile if not cdprofile.connect_sync(cancellable): raise CDError("Could not connect to profile") # Connect to existing device device = device_connect(client, device_id) # Add profile to device try: device.add_profile_sync(Colord.DeviceRelation.HARD, cdprofile, cancellable) except Exception as exception: # Profile may already have been added warnings.warn(safe_str(exception), Warning) # Make profile default for device if not device.make_profile_default_sync(cdprofile, cancellable): raise CDError(errmsg) else: # Find device object path device = get_object_path(device_id, "device") if logfn: logfn("-" * 80) logfn(lang.getstr("commandline")) # Add profile to device # (Ignore returncode as profile may already have been added) args = [cmd, "device-add-profile", device, cdprofile] printcmdline(args[0], args[1:], fn=logfn) if logfn: logfn("") try: p = sp.Popen(args, stdout=sp.PIPE, stderr=sp.STDOUT) stdout, stderr = p.communicate() except Exception as exception: raise CDError(safe_str(exception)) if logfn and stdout.strip(): logfn(stdout.strip()) if logfn: logfn("") logfn(lang.getstr("commandline")) # Make profile default for device args = [cmd, "device-make-profile-default", device, cdprofile] printcmdline(args[0], args[1:], fn=logfn) if logfn: logfn("") try: p = sp.Popen(args, stdout=sp.PIPE, stderr=sp.STDOUT) stdout, stderr = p.communicate() except Exception as exception: raise CDError(safe_str(exception)) else: if p.returncode != 0: raise CDError(stdout.strip() or errmsg) if logfn and stdout.strip(): logfn(stdout.strip())
def get_edid(display_no=0, display_name=None, device=None): """ Get and parse EDID. Return dict. On Mac OS X, you need to specify a display name. On all other platforms, you need to specify a display number (zero-based). """ edid = None if sys.platform == "win32": if not device: # The ordering will work as long as Argyll continues using # EnumDisplayMonitors monitors = util_win.get_real_display_devices_info() moninfo = monitors[display_no] device = util_win.get_active_display_device(moninfo["Device"]) if not device: return {} id = device.DeviceID.split("\\")[1] wmi_connection = None not_main_thread = currentThread().__class__ is not _MainThread if wmi: if not_main_thread: pythoncom.CoInitialize() wmi_connection = wmi.WMI(namespace="WMI") if wmi_connection: # Use WMI for Vista/Win7 # http://msdn.microsoft.com/en-us/library/Aa392707 try: msmonitors = wmi_connection.WmiMonitorDescriptorMethods() except Exception as exception: if not_main_thread: pythoncom.CoUninitialize() raise WMIError(safe_str(exception)) for msmonitor in msmonitors: if msmonitor.InstanceName.split("\\")[1] == id: try: edid = msmonitor.WmiGetMonitorRawEEdidV1Block(0) except: # No EDID entry pass else: edid = "".join(chr(i) for i in edid[0]) break if not_main_thread: pythoncom.CoUninitialize() elif sys.getwindowsversion() < (6, ): # Use registry as fallback for Win2k/XP/2003 # http://msdn.microsoft.com/en-us/library/ff546173%28VS.85%29.aspx # "The Enum tree is reserved for use by operating system components, # and its layout is subject to change. (...) Drivers and Windows # applications must not access the Enum tree directly." # But do we care? Probably not, as older Windows' API isn't likely # gonna change. driver = "\\".join(device.DeviceID.split("\\")[-2:]) subkey = "\\".join( ["SYSTEM", "CurrentControlSet", "Enum", "DISPLAY", id]) try: key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, subkey) except WindowsError: # Registry error safe_print("Windows registry error: Key", "\\".join(["HKEY_LOCAL_MACHINE", subkey]), "does not exist.") return {} numsubkeys, numvalues, mtime = winreg.QueryInfoKey(key) for i in range(numsubkeys): hkname = winreg.EnumKey(key, i) hk = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "\\".join([subkey, hkname])) try: test = winreg.QueryValueEx(hk, "Driver")[0] except WindowsError: # No Driver entry continue if test == driver: # Found our display device try: devparms = winreg.OpenKey( winreg.HKEY_LOCAL_MACHINE, "\\".join([subkey, hkname, "Device Parameters"])) except WindowsError: # No Device Parameters (registry error?) safe_print( "Windows registry error: Key", "\\".join([ "HKEY_LOCAL_MACHINE", subkey, hkname, "Device Parameters" ]), "does not exist.") continue try: edid = winreg.QueryValueEx(devparms, "EDID")[0] except WindowsError: # No EDID entry pass else: raise WMIError("No WMI connection") elif sys.platform == "darwin": # Get EDID via ioreg p = sp.Popen(["ioreg", "-c", "IODisplay", "-S", "-w0"], stdout=sp.PIPE) stdout, stderr = p.communicate() if stdout: for edid in [ binascii.unhexlify(edid_hex) for edid_hex in re.findall( '"IODisplayEDID"\s*=\s*<([0-9A-Fa-f]*)>', stdout) ]: if edid and len(edid) >= 128: parsed_edid = parse_edid(edid) if parsed_edid.get( "monitor_name", parsed_edid.get("ascii")) == display_name: # On Mac OS X, you need to specify a display name # because the order is unknown return parsed_edid return {} elif RDSMM: display = RDSMM.get_display(display_no) if display: edid = display.get("edid") if edid and len(edid) >= 128: return parse_edid(edid) return {}
def send_command(self, command): # Automatically append newline (command end marker) self.sendall(safe_str(command, "UTF-8") + "\n")
from util_dbus import DBusObject, DBusException, BUSTYPE_SYSTEM from util_os import which from util_str import safe_str, safe_unicode import localization as lang if sys.platform not in ("darwin", "win32"): from defaultpaths import xdg_data_home if not Colord: try: Colord = DBusObject(BUSTYPE_SYSTEM, "org.freedesktop.ColorManager", "/org/freedesktop/ColorManager") except DBusException as exception: warnings.warn(safe_str(exception), Warning) # See colord/cd-client.c CD_CLIENT_IMPORT_DAEMON_TIMEOUT = 5000 # ms if (not Colord or isinstance(Colord, DBusObject) or not hasattr(Colord, 'quirk_vendor_name')): from config import get_data_path # From colord/lib/colord/cd_quirk.c, cd_quirk_vendor_name quirk_cache = { "suffixes": [ "Co.", "Co", "Inc.", "Inc", "Ltd.", "Ltd", "Corporation", "Incorporated", "Limited", "GmbH", "corp." ], "vendor_names": {
def init(lib=None, samplerate=22050, channels=2, buffersize=2048, reinit=False): """ (Re-)Initialize sound subsystem """ # Note on buffer size: Too high values cause crackling during fade, too low # values cause choppy playback of ogg files when using pyo (good value for # pyo is >= 2048) global _initialized, _lib, _lib_version, _server, pyglet, pyo, sdl, wx if _initialized and not reinit: # To re-initialize, explicitly set reinit to True return # Select the audio library we're going to use. # User choice or SDL > pyglet > pyo > wx if not lib: if sys.platform in ("darwin", "win32"): # Mac OS X, Windows libs = ("pyglet", "SDL", "pyo", "wx") else: # Linux libs = ("SDL", "pyglet", "pyo", "wx") for lib in libs: try: return init(lib, samplerate, channels, buffersize, reinit) except Exception as exception: pass raise exception elif lib == "pyglet": if not getattr(sys, "frozen", False): # Use included pyglet lib_dir = os.path.join(os.path.dirname(__file__), "lib") if not lib_dir in sys.path: sys.path.insert(0, lib_dir) try: import pyglet version = [] for item in pyglet.version.split("."): try: version.append(int(item)) except ValueError: version.append(item) if version < [1, 2, 2]: raise ImportError("pyglet version %s is too old" % pyglet.version) _lib = "pyglet" except ImportError: _lib = None else: # Work around localization preventing fallback to RIFFSourceLoader pyglet.lib.LibraryLoader.darwin_not_found_error = "" pyglet.lib.LibraryLoader.linux_not_found_error = "" # Set audio driver preference pyglet.options["audio"] = ("pulse", "openal", "directsound", "silent") _server = pyglet.media _lib_version = pyglet.version elif lib == "pyo": try: import pyo _lib = "pyo" except ImportError: _lib = None else: if isinstance(_server, pyo.Server): _server.reinit(sr=samplerate, nchnls=channels, buffersize=buffersize, duplex=0) else: _server = pyo.Server(sr=samplerate, nchnls=channels, buffersize=buffersize, duplex=0, winhost="asio").boot() _server.start() _lib_version = ".".join(str(v) for v in pyo.getVersion()) elif lib == "SDL": SDL_INIT_AUDIO = 16 AUDIO_S16LSB = 0x8010 AUDIO_S16MSB = 0x9010 if sys.byteorder == "little": MIX_DEFAULT_FORMAT = AUDIO_S16LSB else: MIX_DEFAULT_FORMAT = AUDIO_S16MSB if sys.platform == "win32": pth = getenvu("PATH") libpth = os.path.join(pydir, "lib") if not pth.startswith(libpth + os.pathsep): pth = libpth + os.pathsep + pth os.environ["PATH"] = safe_str(pth) elif sys.platform == "darwin": x_framework_pth = os.getenv("X_DYLD_FALLBACK_FRAMEWORK_PATH") if x_framework_pth: framework_pth = os.getenv("DYLD_FALLBACK_FRAMEWORK_PATH") if framework_pth: x_framework_pth = os.pathsep.join( [x_framework_pth, framework_pth]) os.environ["DYLD_FALLBACK_FRAMEWORK_PATH"] = x_framework_pth for libname in ("SDL2", "SDL2_mixer", "SDL", "SDL_mixer"): handle = None if sys.platform in ("darwin", "win32"): libfn = ctypes.util.find_library(libname) if sys.platform == "win32": if libfn and win32api: # Support for unicode paths libfn = safe_unicode(libfn) try: handle = win32api.LoadLibrary(libfn) except pywintypes.error: pass elif sys.platform != "darwin": # Hard-code lib names for Linux libfn = "lib" + libname if libname.startswith("SDL2"): # SDL 2.0 libfn += "-2.0.so.0" else: # SDL 1.2 libfn += "-1.2.so.0" dll = dlopen(libfn, handle=handle) if dll: safe_print("%s:" % libname, libfn) if libname.endswith("_mixer"): if not dll: continue if not sdl: raise RuntimeError("SDL library not loaded") sdl.SDL_RWFromFile.restype = POINTER(SDL_RWops) _server = dll _server.Mix_OpenAudio.argtypes = [ c_int, c_uint16, c_int, c_int ] _server.Mix_LoadWAV_RW.argtypes = [POINTER(SDL_RWops), c_int] _server.Mix_LoadWAV_RW.restype = POINTER(Mix_Chunk) _server.Mix_PlayChannelTimed.argtypes = [ c_int, POINTER(Mix_Chunk), c_int, c_int ] _server.Mix_VolumeChunk.argtypes = [POINTER(Mix_Chunk), c_int] if _initialized: _server.Mix_Quit() sdl.SDL_Quit() sdl.SDL_Init(SDL_INIT_AUDIO) _server.Mix_OpenAudio(samplerate, MIX_DEFAULT_FORMAT, channels, buffersize) _lib = "SDL" if libname.startswith("SDL2"): _lib_version = "2.0" else: _lib_version = "1.2" break else: sdl = dll _server = None elif lib == "wx": try: import wx _lib = "wx" except ImportError: _lib = None else: _server = wx _lib_version = wx.__version__ if not _lib: raise RuntimeError("No audio library available") _initialized = True return _server
def _write_dpx(self, stream, dimensions=None): # Very helpful: http://www.fileformat.info/format/dpx/egff.htm # http://www.simplesystems.org/users/bfriesen/dpx/S268M_Revised.pdf # Generic file header (768 bytes) stream.write("SDPX") # Magic number stream.write(struct.pack(">I", 8192)) # Offset to image data stream.write("V2.0\0\0\0\0") # ASCII version # Optimize for single color optimize = len(self.data) == 1 and len( self.data[0]) == 1 and dimensions # Image data imgdata = [] # 10-bit code adapted from GraphicsMagick dpx.c:WriteSamples if self.bitdepth == 10: shifts = (22, 12, 2) # RGB for i, scanline in enumerate(self.data): if self.bitdepth == 10: packed = [] for RGB in scanline: packed_u32 = 0 for datum, sample in enumerate(RGB): packed_u32 |= (sample << shifts[datum]) packed.append(struct.pack(">I", packed_u32)) scanline = "".join(packed) else: scanline = "".join("".join(self._pack(v) for v in RGB) for RGB in scanline) if not optimize: # Pad lines with binary zeros so they end on 4-byte boundaries scanline = scanline.ljust( int(math.ceil(len(scanline) / 4.0)) * 4, "\0") imgdata.append(scanline) imgdata = "".join(imgdata) if optimize: # Optimize for single color imgdata *= dimensions[0] # Pad lines with binary zeros so they end on 4-byte boundaries imgdata = imgdata.ljust( int(math.ceil(len(imgdata) / 4.0)) * 4, "\0") imgdata *= dimensions[1] w, h = dimensions else: w, h = len(self.data[0]), len(self.data) # Generic file header (cont.) stream.write(struct.pack(">I", 8192 + len(imgdata))) # File size stream.write("\0\0\0\1") # DittoKey (1 = not same as previous frame) stream.write(struct.pack(">I", 768 + 640 + 256)) # Generic section header length stream.write(struct.pack( ">I", 256 + 128)) # Industry-specific section header length stream.write(struct.pack(">I", 0)) # User-defined data length stream.write(safe_str(stream.name or "").ljust(100, "\0")[-100:]) # File name # Date & timestamp tzoffset = round( (time.mktime(time.localtime()) - time.mktime(time.gmtime())) / 60.0 / 60.0) if tzoffset < 0: tzoffset = "%.2i" % tzoffset else: tzoffset = "+%.2i" % tzoffset stream.write(time.strftime("%Y:%m:%d:%H:%M:%S") + tzoffset + "\0\0") stream.write(safe_str("%s %s" % (appname, version)).ljust( 100, "\0")) # Creator stream.write("\0" * 200) # Project stream.write("\0" * 200) # Copyright stream.write("\xff" * 4) # EncryptKey 0xffffffff = not encrypted stream.write("\0" * 104) # Reserved # Generic image header (640 bytes) stream.write("\0\0") # Orientation 0 = left to right, top to bottom stream.write("\0\1") # Number of image elements stream.write(struct.pack(">I", w)) # Pixels per line stream.write(struct.pack(">I", h)) # Lines per image element # Generic image header - image element stream.write("\0" * 4) # 0 = unsigned data stream.write("\0" * 4) # Reference low data code value stream.write("\xff" * 4) # Reference low quantity stream.write(struct.pack(">I", 2**self.bitdepth - 1)) # Reference high data code value stream.write("\xff" * 4) # Reference high quantity stream.write(chr(50)) # Descriptor 50 = RGB stream.write("\2") # Transfer 2 = linear stream.write("\2") # Colorimetric 2 = not applicable stream.write(chr(self.bitdepth)) # BitSize stream.write("\0\1") # Packing 1 = filled 32-bit words stream.write("\0\0") # Encoding 0 = not encoded stream.write(struct.pack(">I", 8192)) # Image data offset stream.write("\0" * 4) # End of line padding stream.write("\0" * 4) # End of image padding stream.write("RGB / Linear".ljust(32, "\0")) # Description # Seven additional unused image elements stream.write("\0" * 72 * 7) # Generic image header (cont.) stream.write("\0" * 52) # Reserved # Generic image source header (256 bytes) sw, sh = [ self.extrainfo.get("original_" + dim, locals()[dim[0]]) for dim in ("width", "height") ] # X offset stream.write( struct.pack(">I", self.extrainfo.get("offset_x", (sw - w) / 2))) # Y offset stream.write( struct.pack(">I", self.extrainfo.get("offset_y", (sh - h) / 2))) # X center stream.write( struct.pack(">f", self.extrainfo.get("center_x", sw / 2.0))) # Y center stream.write( struct.pack(">f", self.extrainfo.get("center_y", sh / 2.0))) stream.write(struct.pack(">I", sw)) # X original size stream.write(struct.pack(">I", sh)) # Y original size stream.write("\0" * 100) # Source image file name stream.write("\0" * 24) # Source image date & timestamp stream.write("\0" * 32) # Input device name stream.write("\0" * 32) # Input device serial number stream.write("\0" * 2 * 4) # Border stream.write("\0\0\0\1" * 2) # Pixel aspect ratio stream.write("\xff" * 4) # X scanned size stream.write("\xff" * 4) # Y scanned size stream.write("\0" * 20) # Reserved # Industry-specific film info header (256 bytes) stream.write("\0" * 2) # Film mfg. ID code stream.write("\0" * 2) # Film type stream.write("\0" * 2) # Offset in perfs stream.write("\0" * 6) # Prefix stream.write("\0" * 4) # Count stream.write("\0" * 32) # Format # Frame position in sequence stream.write( struct.pack(">I", self.extrainfo.get("frame_position", 2**32 - 1))) # Sequence length stream.write( struct.pack(">I", self.extrainfo.get("sequence_length", 2**32 - 1))) # Held count stream.write(struct.pack(">I", self.extrainfo.get("held_count", 1))) # Frame rate of original if "frame_rate" in self.extrainfo: stream.write(struct.pack(">f", self.extrainfo["frame_rate"])) else: stream.write("\xff" * 4) # Shutter angle of camera in degrees stream.write("\xff" * 4) stream.write("\0" * 32) # Frame identification - e.g. keyframe stream.write("\0" * 100) # Slate stream.write("\0" * 56) # Reserved # Industry-specific TV info header (128 bytes) # SMPTE time code stream.write("".join( chr(int(str(v), 16)) for v in self.extrainfo.get("timecode", ["ff"] * 4))) stream.write("\xff" * 4) # User bits stream.write("\xff") # Interlace stream.write("\xff") # Field number stream.write("\xff") # Video signal standard stream.write("\0") # Zero for byte alignment stream.write("\xff" * 4) # H sampling rate Hz stream.write("\xff" * 4) # V sampling rate Hz # Temporal sampling or frame rate Hz if "frame_rate" in self.extrainfo: stream.write(struct.pack(">f", self.extrainfo["frame_rate"])) else: stream.write("\xff" * 4) stream.write("\xff" * 4) # Time offset in ms from sync to 1st pixel stream.write("\xff" * 4) # Gamma stream.write("\xff" * 4) # Black level code value stream.write("\xff" * 4) # Black gain stream.write("\xff" * 4) # Breakpoint stream.write("\xff" * 4) # Reference white level code value stream.write("\xff" * 4) # Integration time in s stream.write("\0" * 76) # Reserved # Padding so image data begins at 8K boundary stream.write("\0" * 6144) # Write image data stream.write(imgdata)
def __init__(self, exception, bus_name=None): self._dbus_error_name = getattr(exception, "get_dbus_name", lambda: None)() if self._dbus_error_name == "org.freedesktop.DBus.Error.ServiceUnknown": exception = "%s: %s" % (exception, bus_name) DBusException.__init__(self, safe_str(exception))