From 223f2c59193721a86309d26098fcc2421fa5ad04 Mon Sep 17 00:00:00 2001 From: Benoit Besson Date: Sun, 11 Feb 2018 10:08:25 +0100 Subject: [PATCH 1/5] fix push init files patches for live 10 --- Devices/Push/__init__.py | 62 +++++++++++++++++++++---------------- Devices/Push/__init__.pyc | Bin 0 -> 1485 bytes Devices/Push2/__init__.py | 60 +++++++++++++++++++---------------- Devices/Push2/__init__.pyc | Bin 0 -> 1446 bytes 4 files changed, 68 insertions(+), 54 deletions(-) create mode 100644 Devices/Push/__init__.pyc create mode 100644 Devices/Push2/__init__.pyc diff --git a/Devices/Push/__init__.py b/Devices/Push/__init__.py index 7ae10c2..0429ae2 100644 --- a/Devices/Push/__init__.py +++ b/Devices/Push/__init__.py @@ -1,27 +1,35 @@ -# Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/__init__.py -from __future__ import absolute_import, print_function -from ableton.v2.control_surface.capabilities import controller_id, inport, outport, AUTO_LOAD_KEY, CONTROLLER_ID_KEY, FIRMWARE_KEY, HIDDEN, NOTES_CC, PORTS_KEY, SCRIPT, SYNC, TYPE_KEY -from .firmware_handling import get_provided_firmware_version -from .push import Push - -from Ubermap import UbermapDevicesPatches - -def get_capabilities(): - return {CONTROLLER_ID_KEY: controller_id(vendor_id=2536, product_ids=[21], model_name='Ableton Push'), - PORTS_KEY: [inport(props=[HIDDEN, NOTES_CC, SCRIPT]), - inport(props=[]), - outport(props=[HIDDEN, - NOTES_CC, - SYNC, - SCRIPT]), - outport(props=[])], - TYPE_KEY: 'push', - FIRMWARE_KEY: get_provided_firmware_version(), - AUTO_LOAD_KEY: True} - -def create_instance(c_instance): - """ Creates and returns the Push script """ - - UbermapDevicesPatches.apply_ubermap_patches() - - return Push(c_instance=c_instance) +# Embedded file name: c:\Jenkins\live\output\win_64_static\Release\python-bundle\MIDI Remote Scripts\Push\__init__.py +from __future__ import absolute_import, print_function, unicode_literals +from ableton.v2.control_surface.capabilities import controller_id, inport, outport, AUTO_LOAD_KEY, CONTROLLER_ID_KEY, FIRMWARE_KEY, HIDDEN, NOTES_CC, PORTS_KEY, SCRIPT, SYNC, TYPE_KEY +from .firmware_handling import get_provided_firmware_version +from .push import Push + +#FIX TO WORK WITH CLYPHX +#from Ubermap import UbermapDevicesPatches +#END OF FIX + +def get_capabilities(): + return {CONTROLLER_ID_KEY: controller_id(vendor_id=2536, product_ids=[21], model_name=u'Ableton Push'), + PORTS_KEY: [inport(props=[HIDDEN, NOTES_CC, SCRIPT]), + inport(props=[]), + outport(props=[HIDDEN, + NOTES_CC, + SYNC, + SCRIPT]), + outport(props=[])], + TYPE_KEY: u'push', + FIRMWARE_KEY: get_provided_firmware_version(), + AUTO_LOAD_KEY: True} + + +def create_instance(c_instance): + u""" Creates and returns the Push script """ + +#FIX TO WORK WITH CLYPHX + from Ubermap import UbermapDevicesPatches +#END OF FIX +#FIX MULTIPLE VERSION BEING +# UbermapDevicesPatches.apply_ubermap_patches() + UbermapDevicesPatches.apply_ubermap_patches(True) +#FIX END + return Push(c_instance=c_instance) \ No newline at end of file diff --git a/Devices/Push/__init__.pyc b/Devices/Push/__init__.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c14f060e323643ddebf629b3591097b2fa3f1f29 GIT binary patch literal 1485 zcmZ`(O>ZMb5Uuw3BX*p`o82rRK(dflj5tKVAt!`3a*T)ww$=6ur7x|?Ovh<7Ju{lF zF#m z9KZ=s0$c}F2V4Xy0>Nt?$h+WrpnBl?p!(njpa$UfK<$AWf*OJwff|9^2el7w3~CJS z0Mr4vLr{m{jzArOn}C{7#R#%4BY zNEfwy`#2(lM`V&4U*-)OZCzE?h=&xbYFnVbZHg3aS>S|1O<~hAGdj0u>LmB^mI{Wm$b2N?J!T3af% z0wx>@ zjT!p0md{1NVrPo1WCrZNbW=)V7R#(jkz(GS&@=5PbrOlWE)r)N#`^pwH&_-^Zk4VO zHdVgi?kft#tOm(ik<6y#xMUwG8PoTP@vH%@ zZDCQ9uy*E~uTQJDL2k@YnpDY+CBa$axwL=D+r<~+M2y8yMD!kt=VBm6B4uiM9Qmq& zrLV}LdE~JRBl(8_@lL?69p>acJns_+;6AF1I0J@XzL1z(%vzbCoQ%*e^ zttBr@#!>Qt_$8U7RmbV>+td3g*S@K5lhm9(C8rfg&_)mgpVaDwCGbQqK_EdiK`$(o z@IUY{f_H>^Zi}ttCW3ZYg#iZ1?8{HdJR%Uh55T}je@AL>a`QbmN;I@X2Q=q!++ntTP1Yy>EQb0Nl0!4C&e$Ij3^Ii z6;R%xRfqDBRv`sxhdvUmx|D|E^eFApBI+T{@?KF0@KzZ?w&;viANOVpVMm zuU|Gr;%!;@U4)v#CS_`LX1%H7%n79c3)}dQnbIdX;DgF7r43PFyL3+Uy2CU;AO(#+ ztpVDibU+^{A`7cd|5o0H}2Jgk>^1mt#XZc2#z9#`MWT2i`_dL?Imb`U1r)f z^~*RhO2)PW%*8@xn2P@mk@0N0RI}sbiPA@h`uXI<_Yt*)OqJbdM~8=#sUN_d&X$vf z9*+gG7^|cC(r+PNHeTRe_=}V2SWY~jspUd8&vZXGVUg42D?ENJPfYm+sF56a3>fB z30L4VF;3L?7S0dq3-Ay?Xdz|tP;6kkw85is4mCmu5M(Pf(Io4l56N_(wGEUg`pmW{ zAJC?UoF2X2=DB{rw&&PZbjB)TopruShgr3U=c)3jM-e}=o_nFn(zpGFf=n&0Yh4yv zZk&tPMmt;lC-a0n62vqnU6{n1^pY}fAmPQSsq?rxG-npLdF+!{kSI$pL5rP_i^Pb| zM2RBqR(4EF-2$!^FW+jxsM`oC2$+NblWP}rQ>C#t>K-p~%P(rH-#Nf!;;PEt=%%Hl zs|zyRg{OE~n22Yk?z7>-mkM!bYIH`n`d_K=3oEG&xO_VzS9jb%R?5xbk8n5K38zv} unxXL?^G$8ERt!=+BgI2eEHCvZ%=fatlIZ}*N9a?Nna7;(nEJim_O&ls6)2Mc literal 0 HcmV?d00001 From 0e1e57d6e0a7f36e26dd1b5224bdc29567343b2b Mon Sep 17 00:00:00 2001 From: Benoit Besson Date: Sun, 11 Feb 2018 12:13:41 +0100 Subject: [PATCH 2/5] comment for remaining error on push 2 --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index bd2d13e..dfe4661 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,10 @@ +# WARNING : for live 10 version + +Need to pach file MIDI Remote Scripts\Push2\model\repr.pyc for method DeviceParameterAdapter._get_image_filenames line 173 : +# except (AttributeError, RuntimeError): +# fix for ubermap + except (AttributeError, RuntimeError, ArgumentError): + # Ubermap v0.1 alpha ## Introduction From 011290fb0b6dfffa55ddcc74c7b456a170d26830 Mon Sep 17 00:00:00 2001 From: Benoit Besson Date: Sun, 11 Feb 2018 12:18:10 +0100 Subject: [PATCH 3/5] update README --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dfe4661..c2fc1c4 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,10 @@ # WARNING : for live 10 version Need to pach file MIDI Remote Scripts\Push2\model\repr.pyc for method DeviceParameterAdapter._get_image_filenames line 173 : -# except (AttributeError, RuntimeError): -# fix for ubermap + except (AttributeError, RuntimeError): +=> shoud be : except (AttributeError, RuntimeError, ArgumentError): +This should be done adding a new method in apply_ubermap_patches() # Ubermap v0.1 alpha From eb275e48ea32dfcbdf1439a37e4db7eb40f0cb3c Mon Sep 17 00:00:00 2001 From: Benoit Besson Date: Sun, 11 Feb 2018 12:18:54 +0100 Subject: [PATCH 4/5] update README --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index c2fc1c4..8105633 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,12 @@ # WARNING : for live 10 version Need to pach file MIDI Remote Scripts\Push2\model\repr.pyc for method DeviceParameterAdapter._get_image_filenames line 173 : + except (AttributeError, RuntimeError): => shoud be : + except (AttributeError, RuntimeError, ArgumentError): + This should be done adding a new method in apply_ubermap_patches() # Ubermap v0.1 alpha From 2bd1af548dfb55adc08613ad55359459b9e5a2a3 Mon Sep 17 00:00:00 2001 From: Benoit Besson Date: Thu, 22 Feb 2018 22:24:09 +0100 Subject: [PATCH 5/5] fixes for live 10 --- Devices/UbermapDevices.py | 59 ++++++--- Devices/UbermapDevicesPatches.py | 182 ++++++++++++++++++++------ README.md | 11 -- UbermapDevicesPatches.py | 213 +++++++++++++++++++++++++++++++ 4 files changed, 397 insertions(+), 68 deletions(-) create mode 100644 UbermapDevicesPatches.py diff --git a/Devices/UbermapDevices.py b/Devices/UbermapDevices.py index 3db5064..ff50838 100644 --- a/Devices/UbermapDevices.py +++ b/Devices/UbermapDevices.py @@ -6,7 +6,9 @@ class UbermapDevices: PARAMS_PER_BANK = 8 - SECTION_BANKS = 'Banks' + SECTION_BANKS = 'Banks' + SECTION_PARAMETER_VALUES = 'ParameterValues' + SECTION_PARAMETER_VALUE_TYPES = 'ParameterValueTypes' SECTION_CONFIG = 'Config' device_config_cache = {} @@ -20,6 +22,9 @@ def get_device_name(self, device): return '' name = device.class_display_name +#BBE TEST BEGIN + log.info('load device name='+device.name+' class_name='+device.class_name+' class_display_name='+device.class_display_name) +#BBE TEST END if self.cfg.get('use_md5'): params = '' for i in device.parameters[1:]: @@ -44,28 +49,14 @@ def dump_device(self, device): config = ConfigObj() config.filename = filepath - config[self.SECTION_BANKS] = {} - config[self.SECTION_CONFIG] = {} + config[self.SECTION_BANKS] = {} + config[self.SECTION_PARAMETER_VALUES] = {} + config[self.SECTION_PARAMETER_VALUE_TYPES] = {} + + config[self.SECTION_CONFIG] = {} config[self.SECTION_CONFIG]['Cache'] = False config[self.SECTION_CONFIG]['Ignore'] = True - ''' - Code to dump original ableton mapping - not working - - bank_names = parameter_bank_names(device, skip = True) - banks = parameter_banks(device, skip = True) - - count = 0 - for bank_name in bank_names: - config[SECTION_BANKS][bank_name] = {} - for param in banks[count]: - if(param): - config[SECTION_BANKS][bank_name][param.original_name] = param.original_name - count = count + 1 - #config[SECTION_BEST_OF]['Bank'] = best_of_parameter_bank(device, _ubermap_skip = True) - config[SECTION_BEST_OF]['Bank'] = config[SECTION_BANKS].itervalues().next() - ''' - count = 0 bank = 1 total_count = 1 @@ -95,6 +86,7 @@ def get_device_config(self, device): def get_custom_device_banks(self, device): device_config = self.get_device_config(device) if(not device_config): + self.dump_device(device) return False return device_config.get(self.SECTION_BANKS).keys() @@ -107,11 +99,38 @@ def get_custom_device_params(self, device, bank_name = None): if(not device_config): return False + def parse_custom_parameter_values(values): + # Split the values on || to see if we have custom value start points specified + values_split = map(lambda s: s.split('||'), values) + has_value_start_points = all(len(x) == 2 for x in values_split) + if not has_value_start_points: + return [values, None] + + return [[x[0] for x in values_split], [float(x[1]) for x in values_split]] + + def get_custom_parameter_values(parameter_name): + values = device_config.get(self.SECTION_PARAMETER_VALUES, parameter_name) + if not values: + return [None, None] + + # If we have an array, i.e. comma separated list, just use that + if isinstance(values, list): + return parse_custom_parameter_values(values) + + # Otherwise try and look up the string key in ParameterValueTypes and use that + values_type = device_config.get(self.SECTION_PARAMETER_VALUE_TYPES, values) + if values_type: + return parse_custom_parameter_values(values_type) + def get_parameter_by_name(device, nameMapping): count = 0 for i in device.parameters: if nameMapping[0] == str(count) + "_" + i.original_name or nameMapping[0] == i.original_name: + log.info("got " + nameMapping[1] + " for " + nameMapping[0]) i.custom_name = nameMapping[1] + + [i.custom_parameter_values, i.custom_parameter_start_points] = get_custom_parameter_values(nameMapping[0]) + return i count = count + 1 diff --git a/Devices/UbermapDevicesPatches.py b/Devices/UbermapDevicesPatches.py index 866b804..8a00333 100644 --- a/Devices/UbermapDevicesPatches.py +++ b/Devices/UbermapDevicesPatches.py @@ -2,36 +2,34 @@ # Applies "monkey patches" to methods within Live's Push implementation to support custom parameter mapping # https://github.com/tomduncalf/ubermap -# Ubermap imports +# Ubermap from Ubermap import UbermapDevices -from Ubermap.UbermapLibs import log - -# DeviceParameterComponent -from pushbase.device_parameter_component import DeviceParameterComponent - -# DeviceParameterBank -from pushbase.device_parameter_bank import DeviceParameterBank - -# BankingUtil -from pushbase import banking_util - -# DeviceComponent -from pushbase.device_component import DeviceComponent -from pushbase.parameter_provider import ParameterInfo - -# Logging +from Ubermap.UbermapLibs import log, config import inspect -# Create singleton UbermapDevices instance -ubermap = UbermapDevices.UbermapDevices() +#def is_v1(): +# return push_version == '1' -def apply_ubermap_patches(): +#FIX MULTIPLE VERSION BEING +#def apply_ubermap_patches(): +def apply_ubermap_patches(is_v1): +#FIX END log.info("Applying UbermapDevices patches") apply_log_method_patches() apply_banking_util_patches() - apply_device_component_patches() +#FIX MULTIPLE VERSION BEING +# apply_device_component_patches() + apply_device_component_patches(is_v1) +#FIX END apply_device_parameter_bank_patches() + apply_device_parameter_adapater_patches() + apply_device_image_filename() + +# Create singleton UbermapDevices instance +ubermap = UbermapDevices.UbermapDevices() +ubermap_config = config.load('global') +#push_version = ubermap_config.get('Push', 'Version') def apply_log_method_patches(): # Log any method calls made to the object - useful for tracing execution flow @@ -42,6 +40,11 @@ def __getattribute__(self, name): log.info('Called ' + self.__class__.__name__ + '::' + str(returned.__name__)) return returned +############################################################################################################ + +# BankingUtil +from pushbase import banking_util + def apply_banking_util_patches(): # device_bank_names - return Ubermap bank names if defined, otherwise use the default device_bank_names_orig = banking_util.device_bank_names @@ -68,23 +71,10 @@ def device_bank_count(device, bank_size = 8, definition = None, definitions = No banking_util.device_bank_count = device_bank_count -def apply_device_component_patches(): - # _get_provided_parameters - return Ubermap parameter names if defined, otherwise use the default - _get_provided_parameters_orig = DeviceComponent._get_provided_parameters - - def _get_provided_parameters(self): - ubermap_params = ubermap.get_custom_device_params(self._decorated_device) - - if ubermap_params: - param_bank = ubermap_params[self._bank.index] - #param_info = map(lambda param: ParameterInfo(parameter=param, name=param.custom_name), param_bank) - param_info = map(lambda parameter: ParameterInfo(parameter=parameter, name=parameter.custom_name, default_encoder_sensitivity=self.default_sensitivity(parameter), fine_grain_encoder_sensitivity=self.fine_sensitivity(parameter)), param_bank) - return param_info +############################################################################################################ - orig_params = _get_provided_parameters_orig(self) - return orig_params - - DeviceComponent._get_provided_parameters = _get_provided_parameters +# DeviceParameterBank +from pushbase.device_parameter_bank import DeviceParameterBank def apply_device_parameter_bank_patches(): # _collect_parameters - this method is called by _update_parameters to determine whether we should @@ -103,3 +93,121 @@ def _collect_parameters(self): return orig DeviceParameterBank._collect_parameters = _collect_parameters + +############################################################################################################ + +# DeviceComponent +from pushbase.device_component import DeviceComponent +from pushbase.parameter_provider import ParameterInfo + +#FIX MULTIPLE VERSION BEING +def apply_device_component_patches(is_v1): + # _get_provided_parameters - return Ubermap parameter names if defined, otherwise use the default + _get_provided_parameters_orig = DeviceComponent._get_provided_parameters + + if is_v1: + from Push.parameter_mapping_sensitivities import parameter_mapping_sensitivity, fine_grain_parameter_mapping_sensitivity + else: + from Push2.parameter_mapping_sensitivities import parameter_mapping_sensitivity, fine_grain_parameter_mapping_sensitivity +#FIX END + + def _get_parameter_info(self, parameter): + if not parameter: + return None + return ParameterInfo(parameter=parameter, name=parameter.custom_name, default_encoder_sensitivity=parameter_mapping_sensitivity(parameter), fine_grain_encoder_sensitivity=fine_grain_parameter_mapping_sensitivity(parameter)) + + def _get_provided_parameters(self): + ubermap_params = ubermap.get_custom_device_params(self._decorated_device) + + if ubermap_params: + param_bank = ubermap_params[self._bank.index] + param_info = map(lambda parameter: _get_parameter_info(self, parameter), param_bank) + return param_info + + orig_params = _get_provided_parameters_orig(self) + return orig_params + + DeviceComponent._get_provided_parameters = _get_provided_parameters + +############################################################################################################ + +# DeviceParameterAdapter +from ableton.v2.base import listenable_property +from Push2.model.repr import DeviceParameterAdapter +from math import floor + +def apply_device_parameter_adapater_patches(): + def name(self): + if hasattr(self._adaptee, 'custom_name'): + return self._adaptee.custom_name + else: + return self._adaptee.name + + DeviceParameterAdapter.name = listenable_property(name) + + def valueItems(self): + if getattr(self._adaptee, 'custom_parameter_values', None): + return self._adaptee.custom_parameter_values + else: + if self._adaptee.is_quantized: + return self._adaptee.value_items + return [] + + DeviceParameterAdapter.valueItems = listenable_property(valueItems) + + def value_to_start_point_index(value, start_points): + log.debug("start_points: " + str(start_points) + ", len: " + str(len(start_points)) + ", value: " + str(value)) + for index, start_point in enumerate(start_points): + log.debug("index: " + str(index) + ", start_point: " + str(start_point) + ", value: " + str(value)) + if value > start_point and (index == len(start_points) - 1 or value < start_points[index + 1]): + log.debug("Input value: " + str(value) + ", output index: " + str(index) + " with custom start points") + return index + + def value_to_index(value, parameter_values): + values_len = len(parameter_values) + value_index = floor(value * values_len) + + # If the value is 1.00 we don't want an off by one error + value_index = value_index - 1 if value_index == values_len else value_index + + log.debug("Input value: " + str(value) + ", output index: " + str(value_index)) + + return value_index + + def value(self): + if getattr(self._adaptee, 'custom_parameter_values', None): + if getattr(self._adaptee, 'custom_parameter_start_points', None): + return value_to_start_point_index(self._adaptee.value, self._adaptee.custom_parameter_start_points) + else: + return value_to_index(self._adaptee.value, self._adaptee.custom_parameter_values) + else: + return self._adaptee.value + + DeviceParameterAdapter.value = listenable_property(value) + +############################################################################################################ + +# DeviceParameterAdapter +from ableton.v2.base import liveobj_valid +from Push2.device_parameter_icons import get_image_filenames, get_image_filenames_from_ids + +def apply_device_image_filename(): + def _get_image_filenames(self, small_images = False): + device = self.canonical_parent + if not hasattr(device, u'class_name'): + return [] + else: + custom_images = None + if liveobj_valid(device): + try: + custom_images = device.get_value_item_icons(getattr(self._adaptee, u'original_parameter', self._adaptee)) +# except (AttributeError, RuntimeError): +# except (AttributeError, RuntimeError, ArgumentError): + except (AttributeError, RuntimeError): + pass + except (ArgumentError): + return [] + + if custom_images is not None: + return get_image_filenames_from_ids(custom_images, small_images) + return get_image_filenames(self.original_name, device.class_name, small_images) \ No newline at end of file diff --git a/README.md b/README.md index 8105633..bd2d13e 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,3 @@ -# WARNING : for live 10 version - -Need to pach file MIDI Remote Scripts\Push2\model\repr.pyc for method DeviceParameterAdapter._get_image_filenames line 173 : - - except (AttributeError, RuntimeError): -=> shoud be : - - except (AttributeError, RuntimeError, ArgumentError): - -This should be done adding a new method in apply_ubermap_patches() - # Ubermap v0.1 alpha ## Introduction diff --git a/UbermapDevicesPatches.py b/UbermapDevicesPatches.py new file mode 100644 index 0000000..8a00333 --- /dev/null +++ b/UbermapDevicesPatches.py @@ -0,0 +1,213 @@ +# Ubermap Devices patches +# Applies "monkey patches" to methods within Live's Push implementation to support custom parameter mapping +# https://github.com/tomduncalf/ubermap + +# Ubermap +from Ubermap import UbermapDevices +from Ubermap.UbermapLibs import log, config +import inspect + +#def is_v1(): +# return push_version == '1' + +#FIX MULTIPLE VERSION BEING +#def apply_ubermap_patches(): +def apply_ubermap_patches(is_v1): +#FIX END + log.info("Applying UbermapDevices patches") + + apply_log_method_patches() + apply_banking_util_patches() +#FIX MULTIPLE VERSION BEING +# apply_device_component_patches() + apply_device_component_patches(is_v1) +#FIX END + apply_device_parameter_bank_patches() + apply_device_parameter_adapater_patches() + apply_device_image_filename() + +# Create singleton UbermapDevices instance +ubermap = UbermapDevices.UbermapDevices() +ubermap_config = config.load('global') +#push_version = ubermap_config.get('Push', 'Version') + +def apply_log_method_patches(): + # Log any method calls made to the object - useful for tracing execution flow + # Use like: DeviceComponent.__getattribute__ = __getattribute__ + def __getattribute__(self, name): + returned = object.__getattribute__(self, name) + if inspect.isfunction(returned) or inspect.ismethod(returned): + log.info('Called ' + self.__class__.__name__ + '::' + str(returned.__name__)) + return returned + +############################################################################################################ + +# BankingUtil +from pushbase import banking_util + +def apply_banking_util_patches(): + # device_bank_names - return Ubermap bank names if defined, otherwise use the default + device_bank_names_orig = banking_util.device_bank_names + + def device_bank_names(device, bank_size = 8, definitions = None): + ubermap_banks = ubermap.get_custom_device_banks(device) + if ubermap_banks: + return ubermap_banks + ubermap.dump_device(device) + + return device_bank_names_orig(device, bank_size, definitions) + + banking_util.device_bank_names = device_bank_names + + # device_bank_count - return Ubermap bank count if defined, otherwise use the default + device_bank_count_orig = banking_util.device_bank_count + + def device_bank_count(device, bank_size = 8, definition = None, definitions = None): + ubermap_banks = ubermap.get_custom_device_banks(device) + if ubermap_banks: + return len(ubermap_banks) + + return device_bank_count_orig(device, bank_size, definition, definitions) + + banking_util.device_bank_count = device_bank_count + +############################################################################################################ + +# DeviceParameterBank +from pushbase.device_parameter_bank import DeviceParameterBank + +def apply_device_parameter_bank_patches(): + # _collect_parameters - this method is called by _update_parameters to determine whether we should + # notify that parameters have been updated or not, but is hardcoded to use the default bank size + # (i.e. full banks of 8), so Ubermap banks with <8 parameters cause later banks to break. Instead return + # the relevant Ubermap bank if defined, otherwise use the default. + _collect_parameters_orig = DeviceParameterBank._collect_parameters + + def _collect_parameters(self): + ubermap_banks = ubermap.get_custom_device_banks(self._device) + if ubermap_banks: + bank = ubermap_banks[self._get_index()] + return bank + + orig = _collect_parameters_orig(self) + return orig + + DeviceParameterBank._collect_parameters = _collect_parameters + +############################################################################################################ + +# DeviceComponent +from pushbase.device_component import DeviceComponent +from pushbase.parameter_provider import ParameterInfo + +#FIX MULTIPLE VERSION BEING +def apply_device_component_patches(is_v1): + # _get_provided_parameters - return Ubermap parameter names if defined, otherwise use the default + _get_provided_parameters_orig = DeviceComponent._get_provided_parameters + + if is_v1: + from Push.parameter_mapping_sensitivities import parameter_mapping_sensitivity, fine_grain_parameter_mapping_sensitivity + else: + from Push2.parameter_mapping_sensitivities import parameter_mapping_sensitivity, fine_grain_parameter_mapping_sensitivity +#FIX END + + def _get_parameter_info(self, parameter): + if not parameter: + return None + return ParameterInfo(parameter=parameter, name=parameter.custom_name, default_encoder_sensitivity=parameter_mapping_sensitivity(parameter), fine_grain_encoder_sensitivity=fine_grain_parameter_mapping_sensitivity(parameter)) + + def _get_provided_parameters(self): + ubermap_params = ubermap.get_custom_device_params(self._decorated_device) + + if ubermap_params: + param_bank = ubermap_params[self._bank.index] + param_info = map(lambda parameter: _get_parameter_info(self, parameter), param_bank) + return param_info + + orig_params = _get_provided_parameters_orig(self) + return orig_params + + DeviceComponent._get_provided_parameters = _get_provided_parameters + +############################################################################################################ + +# DeviceParameterAdapter +from ableton.v2.base import listenable_property +from Push2.model.repr import DeviceParameterAdapter +from math import floor + +def apply_device_parameter_adapater_patches(): + def name(self): + if hasattr(self._adaptee, 'custom_name'): + return self._adaptee.custom_name + else: + return self._adaptee.name + + DeviceParameterAdapter.name = listenable_property(name) + + def valueItems(self): + if getattr(self._adaptee, 'custom_parameter_values', None): + return self._adaptee.custom_parameter_values + else: + if self._adaptee.is_quantized: + return self._adaptee.value_items + return [] + + DeviceParameterAdapter.valueItems = listenable_property(valueItems) + + def value_to_start_point_index(value, start_points): + log.debug("start_points: " + str(start_points) + ", len: " + str(len(start_points)) + ", value: " + str(value)) + for index, start_point in enumerate(start_points): + log.debug("index: " + str(index) + ", start_point: " + str(start_point) + ", value: " + str(value)) + if value > start_point and (index == len(start_points) - 1 or value < start_points[index + 1]): + log.debug("Input value: " + str(value) + ", output index: " + str(index) + " with custom start points") + return index + + def value_to_index(value, parameter_values): + values_len = len(parameter_values) + value_index = floor(value * values_len) + + # If the value is 1.00 we don't want an off by one error + value_index = value_index - 1 if value_index == values_len else value_index + + log.debug("Input value: " + str(value) + ", output index: " + str(value_index)) + + return value_index + + def value(self): + if getattr(self._adaptee, 'custom_parameter_values', None): + if getattr(self._adaptee, 'custom_parameter_start_points', None): + return value_to_start_point_index(self._adaptee.value, self._adaptee.custom_parameter_start_points) + else: + return value_to_index(self._adaptee.value, self._adaptee.custom_parameter_values) + else: + return self._adaptee.value + + DeviceParameterAdapter.value = listenable_property(value) + +############################################################################################################ + +# DeviceParameterAdapter +from ableton.v2.base import liveobj_valid +from Push2.device_parameter_icons import get_image_filenames, get_image_filenames_from_ids + +def apply_device_image_filename(): + def _get_image_filenames(self, small_images = False): + device = self.canonical_parent + if not hasattr(device, u'class_name'): + return [] + else: + custom_images = None + if liveobj_valid(device): + try: + custom_images = device.get_value_item_icons(getattr(self._adaptee, u'original_parameter', self._adaptee)) +# except (AttributeError, RuntimeError): +# except (AttributeError, RuntimeError, ArgumentError): + except (AttributeError, RuntimeError): + pass + except (ArgumentError): + return [] + + if custom_images is not None: + return get_image_filenames_from_ids(custom_images, small_images) + return get_image_filenames(self.original_name, device.class_name, small_images) \ No newline at end of file