Skip to content

Commit

Permalink
Merge pull request #8 from MiguelGuthridge/v0.4.1
Browse files Browse the repository at this point in the history
Merge v0.4.1 Stage to Main
  • Loading branch information
MaddyGuthridge authored Mar 17, 2022
2 parents f881510 + 93eebb8 commit 74feb02
Show file tree
Hide file tree
Showing 37 changed files with 692 additions and 213 deletions.
26 changes: 22 additions & 4 deletions common/activitystate.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@
* Miguel Guthridge [[email protected], HDSQ#2154]
"""

from common.util.apifixes import PluginIndex, UnsafeIndex, GeneratorIndex, \
EffectIndex, WindowIndex
from common.logger import log, verbosity
from common.util.apifixes import (
PluginIndex,
UnsafeIndex,
GeneratorIndex,
EffectIndex,
WindowIndex,
)
from common.util.apifixes import getFocusedPluginIndex, getFocusedWindowIndex

class ActivityState:
Expand All @@ -28,20 +34,31 @@ def __init__(self) -> None:
self._plugin: PluginIndex = self._generator
self._plug_active = True if self._plugin is not None else False
self._changed = False
self._plug_unsafe = False

def printUpdate(self):
def inspect(self):
"""
Inspect details about the activity state.
"""
print(f"Window: {self._window}, Plugin: {self._plugin}")
print(f"Active: {'plugin' if self._plug_active else 'window'}")
print(f"Updating: {self._doUpdate}")
print(f"Split: {self._split}")
return ''

def _forcePlugUpdate(self) -> None:
"""
Update the active plugin when other things are active (eg windows).
Used so that split windows and plugins behaves correctly.
"""
plugin = getFocusedPluginIndex(force=True)
assert plugin is not None
if plugin is None:
if not self._plug_unsafe:
log("state.active", "Using plugin not from selected channel rack group", verbosity.WARNING)
self._plug_unsafe = True
self._plugin = (-1,)
self._generator = (-1,)
return
self._plugin = plugin
if len(plugin) == 1:
self._generator = plugin # type: ignore
Expand All @@ -63,6 +80,7 @@ def tick(self) -> None:
self._plug_active = False
self._forcePlugUpdate()
elif (plugin := getFocusedPluginIndex()) is not None:
self._plug_unsafe = False
if plugin != self._plugin:
self._changed = True
self._plugin = plugin
Expand Down
2 changes: 1 addition & 1 deletion common/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"""

# Version info
VERSION = (0, 4, 0)
VERSION = (0, 4, 1)

# Sub versions
VERSION_MAJOR = VERSION[0]
Expand Down
10 changes: 10 additions & 0 deletions common/eventpattern/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
"""
common > eventpattern
Contains code for pattern matching with MIDI events, including IEventPattern,
a simple way to match events, and IEventPattern, and interface from which custom
pattern matchers can be derived.
Authors:
* Miguel Guthridge [[email protected], HDSQ#2154]
"""

from .bytematch import ByteMatch, fromNibbles
from .ieventpattern import IEventPattern
Expand Down
15 changes: 12 additions & 3 deletions common/eventpattern/basicpattern.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
"""
common > eventpattern > basicpattern
Contains a basic pattern for recognising MIDI events.
Authors:
* Miguel Guthridge [[email protected], HDSQ#2154]
"""

from typing import TYPE_CHECKING, Any, Callable, Optional

Expand All @@ -10,7 +18,7 @@ class BasicPattern(IEventPattern):
This allows developers to define a complex pattern to match with events,
so that MIDI events from a controller can be recognised and paired with the
matching ControlSurface
matching ControlSurface.
"""

def __init__(
Expand All @@ -21,10 +29,11 @@ def __init__(
data2: Optional[ByteMatch]=None
) -> None:
"""
Create an event pattern
Create a basic event pattern.
It can be used to identify sysex events and standard events, but it
should be noted that the two are exclusive for a single event.
should be noted that the two are exclusive for a single event. If you
need to match both, use a UnionPattern
Each parameter can be one of multiple types:
* `int`: A strict value: any value other than this will not match.
Expand Down
10 changes: 8 additions & 2 deletions common/eventpattern/bytematch.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
"""
common > eventpattern > bytematch
Contains the definition for the byte-match type expression, as well as helper
functions for creating event patterns.
Authors:
* Miguel Guthridge [[email protected], HDSQ#2154]
"""

from typing import TYPE_CHECKING, Type, Union
if TYPE_CHECKING:
Expand All @@ -9,8 +17,6 @@
# Variable type for byte match expression
ByteMatch = Union[int, range, tuple[int, ...], 'ellipsis']



def fromNibbles(upper: ByteMatch, lower: ByteMatch) -> tuple:
"""
Returns a ByteMatch expression from two nibble ByteMatches
Expand Down
18 changes: 10 additions & 8 deletions common/eventpattern/forwardedpattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
* Miguel Guthridge [[email protected], HDSQ#2154]
"""

from typing import TYPE_CHECKING

from common.util.events import decodeForwardedEvent, isEventForwardedHereFrom, eventToString
from common.util.events import decodeForwardedEvent, isEventForwardedHereFrom
from . import IEventPattern, UnionPattern

from common.types import EventData
Expand All @@ -19,13 +17,17 @@ class ForwardedPattern(IEventPattern):
The forwarded pattern is used to parse data from events which were forwarded
from the Universal Event Forwarded device script.
This decodes the forwarded event, then checks it against another provided
pattern.
This allows events to all be processed on the same script, which massively
simplifies things. Refer to device_eventforward.py for a reference on
how the event is stored.
"""
def __init__(self, device_num: int, pattern: IEventPattern) -> None:
"""
Create a ForwardedPattern recogniser
Create a ForwardedPattern recogniser. This is used to pattern match with
events that were forwarded from the Universal Event Forwarder.
### Args:
* `device_num` (`int`): device number to accept events from
Expand All @@ -34,12 +36,12 @@ def __init__(self, device_num: int, pattern: IEventPattern) -> None:
super().__init__()
self._device_num = device_num
self._pattern = pattern

def matchEvent(self, event: 'EventData') -> bool:
# Check if the event was forwarded here
if not isEventForwardedHereFrom(event, self._device_num):
return False

# Extract the event and determine if it matches with the
# underlying pattern
# print(eventToString(eventFromForwarded(event, null+2)))
Expand All @@ -49,7 +51,7 @@ class ForwardedUnionPattern(IEventPattern):
"""
Represents an event that can either be forwarded or direct.
"""

def __init__(self, device_num: int, pattern: IEventPattern) -> None:
"""
Create a ForwardedUnionPattern recogniser
Expand All @@ -59,6 +61,6 @@ def __init__(self, device_num: int, pattern: IEventPattern) -> None:
* `pattern` (`IEventPattern`): pattern to match
"""
self._pattern = UnionPattern(pattern, ForwardedPattern(device_num, pattern))

def matchEvent(self, event: 'EventData') -> bool:
return self._pattern.matchEvent(event)
11 changes: 5 additions & 6 deletions common/eventpattern/ieventpattern.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
"""
common > eventpattern
common > eventpattern > ieventpattern
Contains code for pattern matching with MIDI events, including EventPattern,
a standard way to match events, and IEventPattern, from which custom pattern
matchers can be derived.
Contains the definition for IEventPattern, the interface that all event patterns
must inherit from.
Authors:
* Miguel Guthridge [[email protected], HDSQ#2154]
Expand All @@ -23,9 +22,9 @@ class IEventPattern:
ControlSurfaces.
This class can be extended if a developer wishes to create their own event
pattern for a case where the standard EventPattern class doesn't suffice.
pattern for a case where the standard BasicPattern class doesn't suffice.
"""

@abstractmethod
def matchEvent(self, event: 'EventData') -> bool:
"""
Expand Down
2 changes: 1 addition & 1 deletion common/eventpattern/notepattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class NotePattern(BasicPattern):
"""
def __init__(self, note_num: int, channel_match: ByteMatch = ...) -> None:
"""
Create a NotePattern
Create a NotePattern, in order to recognise note events.
### Args:
* `note_num` (`int`): note number to recognise
Expand Down
2 changes: 1 addition & 1 deletion common/eventpattern/nullpattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ class NullPattern(IEventPattern):
"""
Null patterns won't match with any events
"""

def matchEvent(self, event: 'EventData') -> bool:
return False
9 changes: 5 additions & 4 deletions common/eventpattern/unionpattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,19 @@ class UnionPattern(IEventPattern):
Represents the union of multiple event patterns. A match with any of those
patterns is considered a match overall.
"""

def __init__(self, *patterns: IEventPattern) -> None:
"""
Create a UnionPattern
Create a UnionPattern, which will match with any of the given event
patterns.
Args:
* `*patterns` (`IEventPattern`): event patterns to match, each as
separate arguments
separate arguments. At least two patterns are expected
"""
if len(patterns) < 2:
raise ValueError("Expected at least two event patterns to union")
self._patterns = patterns

def matchEvent(self, event: 'EventData') -> bool:
return any(p.matchEvent(event) for p in self._patterns)
Loading

0 comments on commit 74feb02

Please sign in to comment.