Skip to content

Commit

Permalink
refactor: add Action class
Browse files Browse the repository at this point in the history
  • Loading branch information
nuno-andre committed Jun 9, 2021
1 parent 5569a82 commit 82d5fd6
Show file tree
Hide file tree
Showing 34 changed files with 654 additions and 468 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ _Action_ or a list of _Actions_.

**ClyphX** also includes:

- A component called **Macrobat** that adds new functionality to racks in Live
- A component called **[Macrobat](./docs/macrobat_manual.md)** that adds new functionality to racks in Live
such as the ability to control track mixer parameters or send MIDI messages
from Rack Macros.

Expand Down
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ warn_no_return = false
ignore =
E221, # multiple spaces before operator
E241, # multiple spaces after ':'
E251, # unexpected spaces around keyword / parameter equals
E303, # too many blank lines (2)
E731, # do not assign a lambda expression, use a def
W503, # line break before binary operator
exclude =
.git,
Expand Down
2 changes: 1 addition & 1 deletion src/clyphx/actions/arsenal.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
from _NKFW2.ScaleSettingsComponent import SEQ_OFFSET, FOURTHS_OFFSET, OFFSET_NAMES
S_TYPES = [s.name.upper() for s in SCALE_TYPES] # type: List[Text]
O_NAMES = [o.upper() for o in OFFSET_NAMES] # type: List[Text]
except:
except Exception:
pass

log = logging.getLogger(__name__)
Expand Down
38 changes: 19 additions & 19 deletions src/clyphx/actions/clip.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
if TYPE_CHECKING:
from typing import Any, Optional, Text, Dict, List, Tuple
from ..core.live import DeviceParameter, Track
from ..core.legacy import _DispatchCommand
from ..core.legacy import _DispatchCommand, _SingleDispatch

from ..core.xcomponent import XComponent
from ..core.live import Clip, Conversions
Expand Down Expand Up @@ -52,8 +52,7 @@ def dispatch_actions(self, cmd):
for scmd in cmd:
# TODO: compare with dispatch_device_actions
if scmd.track in self._parent.song().tracks:
_args = scmd.track, scmd.action_name, scmd.args
action = self.get_clip_to_operate_on(*_args)
action = self.get_clip_to_operate_on(scmd)
clip_args = None
if action[0]:
if len(action) > 1:
Expand All @@ -63,41 +62,42 @@ def dispatch_actions(self, cmd):
func(self, action[0], scmd.track, scmd.xclip,
clip_args.replace(clip_args.split()[0], ''))
elif clip_args and clip_args.split()[0].startswith('NOTES'):
args = [a.strip() for a in cmd.args.split() if a.strip()]
self.dispatch_clip_note_action(action[0], args)
# args = [a.strip() for a in cmd.args.split() if a.strip()]
self.dispatch_clip_note_action(action[0], scmd.args)
elif cmd.action_name.startswith('CLIP'):
self.set_clip_on_off(action[0], scmd.track, scmd.xclip, cmd.args)
self.set_clip_on_off(action[0], scmd.track, scmd.xclip, scmd.args)

def get_clip_to_operate_on(self, track, action_name, args):
# type: (Track, Text, Text) -> Tuple[Optional[Clip], Text]
def get_clip_to_operate_on(self, scmd):
# type: (_SingleDispatch) -> Tuple[Optional[Clip], Text]
'''Get clip to operate on and action to perform with args.'''
args = scmd.args
try:
# TODO: add args to parsing
parsed = self._parent.parse_obj('clip', action_name)
parsed = self._parent.parse_obj('clip', scmd.action_name)
except Exception:
try:
parsed, args = self._parse_split_name(action_name, args)
parsed, args = self._parse_split_name(scmd.action_name, args)
except Exception as e:
log.error('Failed to parse clip: %r', e)
return

clip = None
if 'name' in parsed: # CLIP"Name"
clip = self.get_clip_by_name(track, parsed['name'])
clip = self.get_clip_by_name(scmd.track, parsed['name'])
elif 'sel' in parsed: # CLIPSEL
if self.application().view.is_view_visible('Arranger'):
clip = self.song().view.detail_clip
else:
slot_idx = None
if not parsed: # CLIP
if track.playing_slot_index >= 0:
slot_idx = track.playing_slot_index
if scmd.track.playing_slot_index >= 0:
slot_idx = scmd.track.playing_slot_index
elif 'pos' in parsed: # CLIPx
slot_idx = int(parsed['pos']) - 1

slot_idx = self.sel_scene if slot_idx is None else slot_idx
if track.clip_slots[slot_idx].has_clip:
clip = track.clip_slots[slot_idx].clip
if scmd.track.clip_slots[slot_idx].has_clip:
clip = scmd.track.clip_slots[slot_idx].clip
return clip, args

@staticmethod
Expand Down Expand Up @@ -386,7 +386,7 @@ def insert_envelope(self, clip, track, xclip, args):
if 0 <= min_factor and max_factor < 101 and min_factor < max_factor:
env_range = ((min_factor / 100.0) * param.max,
(max_factor / 100.0) * param.max)
except:
except Exception:
pass
self.song().view.detail_clip = clip
clip.view.show_envelope()
Expand Down Expand Up @@ -519,14 +519,14 @@ def quantize(self, clip, track, xclip, args):
strength = float(arg_array[1 + array_offset]) / 100.0
if strength > 1.0 or strength < 0.0:
strength = 1.0
except:
except Exception:
strength = 1.0
if len(arg_array) > 2 + array_offset:
try:
swing_to_apply = float(arg_array[2 + array_offset]) / 100.0
if swing_to_apply > 1.0 or swing_to_apply < 0.0:
swing_to_apply = 0.0
except:
except Exception:
swing_to_apply = 0.0
self.song().swing_amount = swing_to_apply
# apply standard qntz to all
Expand Down Expand Up @@ -576,7 +576,7 @@ def chop_clip(self, clip, track, xclip, args):
if args:
try:
num_chops = int(args)
except:
except Exception:
pass
slot_index = list(track.clip_slots).index(clip.canonical_parent)
current_start = clip.start_marker
Expand Down
4 changes: 2 additions & 2 deletions src/clyphx/actions/clip_env_capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,13 @@ def _get_device_range(args, track):
s, e = dev_args.split('-')
start = int(s) - 1
end = int(e)
except:
except Exception:
start, end = 0, 1
else:
try:
start = int(dev_args) - 1
end = start + 1
except:
except Exception:
pass
if 0 <= start and end <= len(track.devices) and start <= end:
return (start, end)
Expand Down
8 changes: 4 additions & 4 deletions src/clyphx/actions/clip_notes.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,15 @@ def get_pos_range(clip, string):
user_range = string.split('-')
try:
start = float(user_range[0].replace('@', ''))
except:
except Exception:
pass
else:
if start >= 0.0:
pos_range = (start, start)
if len(user_range) > 1:
try:
pos_range = (start, float(user_range[1]))
except:
except Exception:
pass
return pos_range or (clip.loop_start, clip.loop_end)

Expand All @@ -113,7 +113,7 @@ def get_note_range(self, string):
if len(string) > 1:
try:
note_range = pitch_range(string)
except:
except Exception:
try:
start_note = Pitch.first_note(string)
note_range = (start_note, start_note + 1)
Expand Down Expand Up @@ -288,7 +288,7 @@ def do_note_velo_adjustment(self, data):
for n in data.notes_to_edit:
try:
edited.append((n[0], n[1], n[2], float(arg), n[4]))
except:
except Exception:
pass

return edited
Expand Down
12 changes: 9 additions & 3 deletions src/clyphx/actions/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@
TOSIMP = XClipActions.to_simpler,
) # type: Dict[Text, Callable]

NOTES_ACTIONS = dict([
NOTES_ACTIONS = dict((
('REV', NotesMixin.do_note_reverse),
('INV', NotesMixin.do_note_invert),
('COMP', NotesMixin.do_note_compress),
Expand All @@ -172,8 +172,7 @@
('OFF', NotesMixin.set_notes_on_off),
(None, NotesMixin.set_notes_on_off),
('', NotesMixin.set_notes_on_off),
]) # type: Dict[Text, Callable[[Clip, Any], List[None]]]

)) # type: Dict[Text, Callable[[Clip, Any], List[None]]]

DEVICE_ACTIONS = dict(
CSEL = XDeviceActions.adjust_selected_chain,
Expand Down Expand Up @@ -209,6 +208,13 @@
STOP = XDeviceActions.set_looper_state,
) # type: Dict[Text, Callable[[XDeviceActions, Optional[Text]], None]]

CHAIN_ACTIONS = dict(
MUTE = XDeviceActions.mute_chain,
SOLO = XDeviceActions.solo_chain,
VOL = XDeviceActions.adjust_chain_volume,
PAN = XDeviceActions.adjust_chain_panning,
)

DR_ACTIONS = dict(
SCROLL = XDrActions.scroll_selector,
UNMUTE = XDrActions.unmute_all,
Expand Down
12 changes: 6 additions & 6 deletions src/clyphx/actions/control_surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ def _get_script_to_operate_on(self, script_info):
if v['name'] == script_spec:
script = k
break
except:
except Exception:
script = None
return script

Expand Down Expand Up @@ -289,7 +289,7 @@ def handle_track_action(self, script_key, mixer, xclip, ident, args):
else:
track_start = int(track_range) - 1
track_end = track_start + 1
except:
except Exception:
return

if (0 <= track_start and track_start < track_end and
Expand Down Expand Up @@ -333,7 +333,7 @@ def handle_track_bank(self, script_key, xclip, ident, mixer, session, args):
offset = int(args)
if 0 <= (offset + t_offset) < len(tracks):
new_offset = offset + t_offset
except:
except Exception:
return

if new_offset >= 0:
Expand Down Expand Up @@ -369,7 +369,7 @@ def handle_session_offset(self, script_key, session, args):
if new_track == -1 or new_scene == -1:
return
session.set_offsets(new_track, new_scene)
except:
except Exception:
pass

def _parse_ring_spec(self, spec_id, arg_string, default_index, list_to_search):
Expand Down Expand Up @@ -477,7 +477,7 @@ def on_selected_track_changed(self):
if 0 <= centered_id < len(self.song().visible_tracks):
new_trk_id = centered_id
session.set_offsets(new_trk_id, s_offset)
except:
except Exception:
pass

def on_selected_scene_changed(self):
Expand Down Expand Up @@ -509,7 +509,7 @@ def on_selected_scene_changed(self):
if 0 <= centered_id < len(self.song().scenes):
new_scn_id = centered_id
session.set_offsets(t_offset, new_scn_id)
except:
except Exception:
pass


Expand Down
49 changes: 28 additions & 21 deletions src/clyphx/actions/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def adjust_selected_chain(self, device, track, xclip, args):
else:
try:
new_index = int(args) - 1
except:
except Exception:
new_index = list(device.chains).index(device.view.selected_chain)
if 0 <= new_index < len(device.chains):
device.view.selected_chain = device.chains[new_index]
Expand Down Expand Up @@ -187,9 +187,9 @@ def get_chain_selector(device):
# type: (Device) -> Optional[DeviceParameter]
'''Get rack chain selector param.'''
if device.class_name.endswith('GroupDevice'):
for parameter in device.parameters:
if str(parameter.original_name) == 'Chain Selector':
return parameter
for param in device.parameters:
if str(param.original_name) == 'Chain Selector':
return param
return None

@staticmethod
Expand Down Expand Up @@ -219,34 +219,41 @@ def get_bank_param(device, param, bank='B0'):
def dispatch_chain_action(self, device, args):
# type: (Device, List[Text]) -> None
'''Handle actions related to device chains.'''
from .consts import CHAIN_ACTIONS

if not (self._parent._can_have_nested_devices and device.can_have_chains and device.chains):
raise TypeError('This device does not support chain actions.')

try:
chain_num, action, value = args[0:3]
chain_num = chain_num.replace('CHAIN', '').replace('CH', '')
chain = device.chains[int(chain_num) - 1]

chain = device.chains[int(chain_num.replace('CHAIN', '')) - 1]

if action not in {'MUTE', 'SOLO', 'VOL', 'PAN'}:
raise InvalidAction('Invalid device chain action: {}'.format(action))
elif action in {'VOL', 'PAN'} and device.class_name.startswith('Midi'):
if action in {'VOL', 'PAN'} and device.class_name.startswith('Midi'):
raise InvalidAction('Invalid MIDI device chain action: {}'.format(action))
except Exception as e:
log.error("Failed to parse chain action args '%s': %r", args, e)
return

chain = device.view.selected_chain
if chain:
func, obj, param = dict(
# FIXME
MUTE = (switch, chain, 'mute'),
SOLO = (switch, chain, 'solo'),
VOL = (self._adjust_param, chain.mixer_device, 'volume'),
PAN = (self._adjust_param, chain.mixer_device, 'panning'),
)
func(obj, param, value)

# FIXME:
def _adjust_param(self, obj, param, value):
self.adjust_param(getattr(obj, param), value)
try:
func = CHAIN_ACTIONS[action]
except KeyError:
raise InvalidAction('Invalid device chain action: {}'.format(action))
else:
func(chain, value)

def mute_chain(self, chain, value):
switch(chain, 'mute', value)

def solo_chain(self, chain, value):
switch(chain, 'solo', value)

def adjust_chain_volume(self, chain, value):
self.adjust_param(chain.mixer_device.volume, value)

def adjust_chain_panning(self, chain, value):
self.adjust_param(chain.mixer_device.panning, value)

# endregion
5 changes: 5 additions & 0 deletions src/clyphx/actions/device_looper.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
from __future__ import absolute_import, unicode_literals
from builtins import object
from typing import TYPE_CHECKING

from ..consts import LOOPER_STATES, switch
from ..core.exceptions import InvalidParam

if TYPE_CHECKING:
from typing import Text
from ..core.legacy import _DispatchCommand


# TODO: turn into a component?
class LooperMixin(object):
Expand Down
Loading

0 comments on commit 82d5fd6

Please sign in to comment.