def get(self): uname = os.uname() info = { "hardware": safe_json_load("/etc/mod-hardware-descriptor.json", dict), "env": dict( (k, os.environ[k]) for k in [k for k in os.environ.keys() if k.startswith("MOD")]), "python": { "argv": sys.argv, "path": sys.path, "platform": sys.platform, "prefix": sys.prefix, "version": sys.version }, "uname": { "machine": uname.machine, "release": uname.release, "version": uname.version } } self.write(info)
def get_last_bank_and_pedalboard(): data = safe_json_load(LAST_STATE_JSON_FILE, dict) keys = data.keys() if len(keys) == 0 or "bank" not in keys or "pedalboard" not in keys or not isinstance(data['bank'], int): print("last state file does not exist or is corrupt") return (-1, None) return (data['bank']+1, data['pedalboard'])
def get_last_bank_and_pedalboard(): data = safe_json_load(LAST_STATE_JSON_FILE, dict) keys = data.keys() if "bank" not in keys or "pedalboard" not in keys or not isinstance(data['bank'], int): print("last state file does not exist or is corrupt") return (-1, None) return (data['bank']+1, data['pedalboard'])
def __init__(self): prefs = safe_json_load(PREFERENCES_JSON_FILE, dict) if prefs.get("link-enabled-at-boot", "") == "true": prefs["link-enabled"] = "true" if prefs.get("transport-rolling-at-boot", "") == "true": prefs["transport-rolling"] = "true" self.prefs = prefs
def post(self): key = self.get_argument("key") value = self.get_argument("value") data = safe_json_load(PREFERENCES_JSON_FILE, dict) data[key] = value with open(PREFERENCES_JSON_FILE, 'w') as fh: json.dump(data, fh) self.write(True)
def index(self): context = {} user_id = safe_json_load(USER_ID_JSON_FILE, dict) prefs = safe_json_load(PREFERENCES_JSON_FILE, dict) with open(DEFAULT_ICON_TEMPLATE, 'r') as fh: default_icon_template = squeeze(fh.read().replace("'", "\\'")) with open(DEFAULT_SETTINGS_TEMPLATE, 'r') as fh: default_settings_template = squeeze(fh.read().replace("'", "\\'")) pbname = xhtml_escape(SESSION.host.pedalboard_name) prname = SESSION.host.pedalpreset_name() fullpbname = pbname or "Untitled" if prname: fullpbname += " - " + prname context = { 'default_icon_template': default_icon_template, 'default_settings_template': default_settings_template, 'default_pedalboard': DEFAULT_PEDALBOARD, 'cloud_url': CLOUD_HTTP_ADDRESS, 'pedalboards_url': PEDALBOARDS_HTTP_ADDRESS, 'hardware_profile': b64encode(json.dumps(SESSION.get_hardware_actuators()).encode("utf-8")), 'version': self.get_argument('v'), 'lv2_plugin_dir': LV2_PLUGIN_DIR, 'bundlepath': SESSION.host.pedalboard_path, 'title': pbname, 'size': json.dumps(SESSION.host.pedalboard_size), 'fulltitle': fullpbname, 'titleblend': '' if SESSION.host.pedalboard_name else 'blend', 'using_app': 'true' if APP else 'false', 'using_mod': 'true' if DEVICE_KEY else 'false', 'user_name': xhtml_escape(user_id.get("name", "")), 'user_email': xhtml_escape(user_id.get("email", "")), 'favorites': json.dumps(gState.favorites), 'preferences': json.dumps(prefs), } return context
def list_banks(brokenpedalbundles=[], shouldSave=True): banks = safe_json_load(BANKS_JSON_FILE, list) if len(banks) == 0: return [] changed = False checkbroken = len(brokenpedalbundles) > 0 validbanks = [] for bank in banks: validpedals = [] for pb in bank['pedalboards']: if 'bundle' not in pb.keys() or not pb['bundle']: title = pb['title'].encode("ascii", "ignore").decode("ascii") print( "Auto-removing pedalboard '%s' from bank (missing bundle)" % title) changed = True continue if not os.path.exists(pb['bundle']): bundle = pb['bundle'].encode("ascii", "ignore").decode("ascii") print( "ERROR in banks.py: referenced pedalboard does not exist:", bundle) changed = True continue if checkbroken and os.path.abspath( pb['bundle']) in brokenpedalbundles: title = pb['title'].encode("ascii", "ignore").decode("ascii") print("Auto-removing pedalboard '%s' from bank (it's broken)" % title) changed = True continue validpedals.append(pb) if len(validpedals) == 0: title = bank['title'].encode("ascii", "ignore").decode("ascii") print( "Auto-deleting bank with name '%s', as it does not contain any pedalboards" % title) changed = True continue bank['pedalboards'] = validpedals validbanks.append(bank) if changed and shouldSave: save_banks(validbanks) return validbanks
def load(self, bundlepath, instances): datafile = os.path.join(bundlepath, "addressings.json") if not os.path.exists(datafile): return data = safe_json_load(datafile, dict) used_actuators = [] yield gen.Task(self.cchain.wait_initialized) for actuator_uri, addrs in data.items(): for addr in addrs: instance = addr['instance'].replace("/graph/", "", 1) portsymbol = addr['port'] try: instance_id, plugin_uri = instances[instance] except KeyError: print( "ERROR: An instance specified in addressings file is invalid" ) continue curvalue = self._task_get_port_value(instance_id, portsymbol) addrdata = self.add(instance_id, plugin_uri, portsymbol, actuator_uri, addr['label'], addr['minimum'], addr['maximum'], addr['steps'], curvalue) if addrdata is not None: self._task_store_address_data(instance_id, portsymbol, addrdata) if actuator_uri not in used_actuators: used_actuators.append(actuator_uri) for actuator_uri in used_actuators: actuator_type = self.get_actuator_type(actuator_uri) if actuator_type == self.ADDRESSING_TYPE_HMI: yield gen.Task(self.hmi_load_first, actuator_uri) elif actuator_type == self.ADDRESSING_TYPE_CC: self.cc_load_all(actuator_uri) # NOTE: MIDI addressings are not stored in addressings.json. # They must be loaded by calling 'add_midi' before calling this function. self.midi_load_everything()
def list_banks(brokenpedals = []): banks = safe_json_load(BANKS_JSON_FILE, list) if len(banks) == 0: return [] changed = False checkbroken = len(brokenpedals) > 0 validbanks = [] for bank in banks: validpedals = [] for pb in bank['pedalboards']: if 'bundle' not in pb.keys() or not pb['bundle']: title = pb['title'].encode("ascii", "ignore").decode("ascii") print("Auto-removing pedalboard '%s' from bank (missing bundle)" % title) changed = True continue if not os.path.exists(pb['bundle']): bundle = pb['bundle'].encode("ascii", "ignore").decode("ascii") print("ERROR in banks.py: referenced pedalboard does not exist:", bundle) changed = True continue if checkbroken and os.path.abspath(pb['bundle']) in brokenpedals: title = pb['title'].encode("ascii", "ignore").decode("ascii") print("Auto-removing pedalboard '%s' from bank (it's broken)" % title) changed = True continue validpedals.append(pb) if len(validpedals) == 0: title = bank['title'].encode("ascii", "ignore").decode("ascii") print("Auto-deleting bank with name '%s', as it does not contain any pedalboards" % title) changed = True continue bank['pedalboards'] = validpedals validbanks.append(bank) if changed: save_banks(validbanks) return validbanks
def __init__(self, applyFn): self.applyFn = applyFn self.changed = False self.values = self.DEFAULTS.copy() if os.path.exists(self.INTERMEDIATE_PROFILE_PATH): data = safe_json_load(self.INTERMEDIATE_PROFILE_PATH, dict) ensure_data_index_valid(data, 1) self.values.update(data) else: try: with TextFileFlusher(self.INTERMEDIATE_PROFILE_PATH) as fh: json.dump(self.values, fh, indent=4) except IOError: pass fill_in_mixer_values(self.values) ioloop.IOLoop.instance().add_callback(self.apply_first)
def remove_pedalboard_from_banks(pedalboard): newbanks = [] banks = safe_json_load(BANKS_JSON_FILE, list) for bank in banks: newpedalboards = [] for oldpedalboard in bank['pedalboards']: if os.path.abspath(oldpedalboard['bundle']) != os.path.abspath(pedalboard): newpedalboards.append(oldpedalboard) # if there's no pedalboards left ignore this bank (ie, delete it) if len(newpedalboards) == 0: title = bank['title'].encode("ascii", "ignore").decode("ascii") print("Auto-deleting bank with name '%s', as it does not contain any pedalboards" % title) continue bank['pedalboards'] = newpedalboards newbanks.append(bank) save_banks(newbanks)
def prepare(isModApp = False): check_environment() lv2_init() gState.favorites = safe_json_load(FAVORITES_JSON_FILE, list) if len(gState.favorites) > 0: uris = get_plugin_list() for uri in gState.favorites: if uri not in uris: gState.favorites.remove(uri) if False: print("Scanning plugins, this may take a little...") get_all_plugins() print("Done!") if not isModApp: signal(SIGUSR1, signal_recv) signal(SIGUSR2, signal_recv) set_process_name("mod-ui") application.listen(DEVICE_WEBSERVER_PORT, address="0.0.0.0") if LOG: from tornado.log import enable_pretty_logging enable_pretty_logging() def checkhost(): if SESSION.host.readsock is None or SESSION.host.writesock is None: print("Host failed to initialize, is the backend running?") SESSION.host.close_jack() sys.exit(1) elif not SESSION.host.connected: ioinstance.call_later(0.2, checkhost) ioinstance = IOLoop.instance() ioinstance.add_callback(checkhost)
def retrieve(self, index): """Deserialize the profile from JSON stored on harddisk.""" if index < 1 or index > 4: return False # load state filename = index_to_filepath(index) if os.path.exists(filename): data = safe_json_load(filename, dict) data['index'] = index else: data = self.DEFAULTS.copy() data.update(self.DEFAULTS_EXTRA[index]) self.changed = False self.values.update(data) # store everything in intermediate file, now with new values with TextFileFlusher(self.INTERMEDIATE_PROFILE_PATH) as fh: json.dump(self.values, fh, indent=4) # apply the values self.apply(False) return True
def __init__(self): self.prefs = safe_json_load(PREFERENCES_JSON_FILE, dict)
def load(self, bundlepath, instances, skippedPorts): # Check if this is the first time we load addressings (ie, first time mod-ui starts) first_load = self.first_load self.first_load = False # Check if pedalboard contains addressings first datafile = os.path.join(bundlepath, "addressings.json") if not os.path.exists(datafile): self.waiting_for_cc = False return # Load addressings data = safe_json_load(datafile, dict) # Basic setup cc_initialized = self.cchain.initialized has_cc_addrs = False retry_cc_addrs = False used_actuators = [] # NOTE: We need to wait for Control Chain to finish initializing. # Can take some time due to waiting for several device descriptors. # We load everything that is possible first, then wait for Control Chain at the end if not ready yet. # Load all addressings possible for actuator_uri, addrs in data.items(): is_cc = self.get_actuator_type( actuator_uri) == self.ADDRESSING_TYPE_CC if is_cc: has_cc_addrs = True if not cc_initialized: continue # Continue if current actuator_uri is not part of the actual available actuators (hardware, virtual bpm or cc) if actuator_uri not in self.hw_actuators_uris and not is_cc and actuator_uri != kBpmURI: continue i = 0 for addr in addrs: instance = addr['instance'].replace("/graph/", "", 1) portsymbol = addr['port'] try: instance_id, plugin_uri = instances[instance] except KeyError: print( "ERROR: An instance specified in addressings file is invalid" ) continue if len(skippedPorts ) > 0 and instance + "/" + portsymbol in skippedPorts: print( "NOTE: An incompatible addressing has been skipped, port:", instance, portsymbol) continue page = addr.get('page', None) # Dealing with HMI addr from a pedalboard not supporting pages on a device supporting them if self.get_actuator_type( actuator_uri ) == self.ADDRESSING_TYPE_HMI and self.pages_cb and self.pages_nb and page is None: if i < self.pages_nb: # automatically assign the i-th assignment to page i page = i else: # cannot address more because we've reached the max nb of pages for current actuator break curvalue = self._task_get_port_value(instance_id, portsymbol) group = addr.get('group', None) addrdata = self.add(instance_id, plugin_uri, portsymbol, actuator_uri, addr['label'], addr['minimum'], addr['maximum'], addr['steps'], curvalue, addr.get('tempo'), addr.get('dividers'), page, group) if addrdata is not None: stored_addrdata = addrdata.copy() if group is not None: # if addressing is grouped, then store address data using group actuator uri stored_addrdata['actuator_uri'] = group self._task_store_address_data(instance_id, portsymbol, stored_addrdata) if actuator_uri not in used_actuators: used_actuators.append(actuator_uri) elif is_cc: # Control Chain is initialized but addressing failed to load (likely due to missing hardware) # Set this flag so we wait for devices later retry_cc_addrs = True i += 1 # Load HMI and Control Chain addressings for actuator_uri in used_actuators: if self.get_actuator_type( actuator_uri) == self.ADDRESSING_TYPE_HMI: try: yield gen.Task(self.hmi_load_first, actuator_uri) except Exception as e: logging.exception(e) yield gen.Task(self.hmi_load_first, actuator_uri) elif self.get_actuator_type( actuator_uri ) == self.ADDRESSING_TYPE_CC and cc_initialized: self.cc_load_all(actuator_uri) # Load MIDI addressings # NOTE: MIDI addressings are not stored in addressings.json. # They must be loaded by calling 'add_midi' before calling this function. self.midi_load_everything() # Unset retry flag if at least 1 Control Chain device is connected if retry_cc_addrs and len(self.cc_metadata) > 0: retry_cc_addrs = False # Check if we need to wait for Control Chain if not first_load or (cc_initialized and not retry_cc_addrs): self.waiting_for_cc = False return if retry_cc_addrs: # Wait for any Control Chain devices to appear, with 10s maximum time-out print("NOTE: Waiting for Control Chain devices to appear") for i in range(10): yield gen.sleep(1) if len(self.cc_metadata) > 0 and self.cchain.initialized: break elif not self.cchain.initialized: # Control Chain was not initialized yet by this point, wait for it # 'wait_initialized' will time-out in 10s if nothing happens print("NOTE: Waiting for Control Chain to initialize") try: yield gen.Task(self.cchain.wait_initialized) except Exception as e: logging.exception(e) self.waiting_for_cc = False for cb in self.waiting_for_cc_cbs: cb() self.waiting_for_cc_cbs = [] # Don't bother continuing if there are no Control Chain addressesings if not has_cc_addrs: return # Don't bother continuing if there are no Control Chain devices available if len(self.cc_metadata) == 0: print( "WARNING: Pedalboard has Control Chain addressings but no devices are available" ) return # reset used actuators, only load for those that succeed used_actuators = [] # Re-do the same as we did above for actuator_uri, addrs in data.items(): if self.get_actuator_type(actuator_uri) != self.ADDRESSING_TYPE_CC: continue for addr in addrs: instance = addr['instance'].replace("/graph/", "", 1) portsymbol = addr['port'] try: instance_id, plugin_uri = instances[instance] except KeyError: print( "ERROR: An instance specified in addressings file is invalid" ) continue if len(skippedPorts ) > 0 and instance + "/" + portsymbol in skippedPorts: print( "NOTE: An incompatible addressing has been skipped, port:", instance, portsymbol) continue curvalue = self._task_get_port_value(instance_id, portsymbol) addrdata = self.add(instance_id, plugin_uri, portsymbol, actuator_uri, addr['label'], addr['minimum'], addr['maximum'], addr['steps'], curvalue) if addrdata is not None: self._task_store_address_data(instance_id, portsymbol, addrdata) if actuator_uri not in used_actuators: used_actuators.append(actuator_uri) for actuator_uri in used_actuators: self.cc_load_all(actuator_uri)