From cbb30981503141abfbbb7fff682326a3cd70aa3c Mon Sep 17 00:00:00 2001 From: Alberto Fanjul Date: Fri, 25 Mar 2022 20:31:46 +0100 Subject: [PATCH 01/13] Avoid circular dependency --- grid_instrument/__init__.py | 1 - play.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/grid_instrument/__init__.py b/grid_instrument/__init__.py index ac725ce..e69de29 100644 --- a/grid_instrument/__init__.py +++ b/grid_instrument/__init__.py @@ -1 +0,0 @@ -from grid_instrument import GridInstrument \ No newline at end of file diff --git a/play.py b/play.py index cd06cd7..69a1173 100755 --- a/play.py +++ b/play.py @@ -9,6 +9,7 @@ # import grid_instrument +from grid_instrument import grid_instrument import rtmidi import time From 7d763f83c4fe425be1f856642e8f6c9b574f5861 Mon Sep 17 00:00:00 2001 From: Alberto Fanjul Date: Fri, 25 Mar 2022 20:32:06 +0100 Subject: [PATCH 02/13] locate python from environment --- play.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/play.py b/play.py index 69a1173..412d93e 100755 --- a/play.py +++ b/play.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # # Quick usage example of "grid_instrument" with MIDI output port. # Works with all Launchpads: Mk1, Mk2, S/Mini, Pro, XL and LaunchKey From 90295b657557bd617220452155dfdf1ff048f4b0 Mon Sep 17 00:00:00 2001 From: Alberto Fanjul Date: Fri, 25 Mar 2022 20:33:06 +0100 Subject: [PATCH 03/13] Use module launchpad_py --- grid_instrument/grid_instrument.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grid_instrument/grid_instrument.py b/grid_instrument/grid_instrument.py index 9061cc8..563fee1 100644 --- a/grid_instrument/grid_instrument.py +++ b/grid_instrument/grid_instrument.py @@ -4,12 +4,12 @@ import collections try: - import launchpad_rtmidi_py as launchpad + import launchpad_py as launchpad except ImportError: try: - import launchpad_rtmidi_py + import launchpad_py except ImportError: - sys.exit("error loading launchpad_rtmidi.py") + sys.exit("error loading launchpad_py") class GridInstrument: From b9990f987a3a24112f84eac21de5b441b021c6ab Mon Sep 17 00:00:00 2001 From: Alberto Fanjul Date: Fri, 25 Mar 2022 20:34:56 +0100 Subject: [PATCH 04/13] Use python3 print --- grid_instrument/grid_instrument.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grid_instrument/grid_instrument.py b/grid_instrument/grid_instrument.py index 563fee1..9813251 100644 --- a/grid_instrument/grid_instrument.py +++ b/grid_instrument/grid_instrument.py @@ -207,7 +207,7 @@ def _main_loop(self): # Grid Key self._grid_key = self.WHITE_KEYS[x - 1] + (y == 7) self._color_buttons() - print "Key is ", self.NOTE_NAMES[self._grid_key] + print("Key is ", self.NOTE_NAMES[self._grid_key]) elif (1 <= x <= 8) and (1 <= y <= 4): self._grid_musical_mode_button_pressed(x, y) if x in [1, 2] and y == 9 and pressed and (self.kid_mode is not True): @@ -398,7 +398,7 @@ def _button_pressed(self, x, y, velocity): self._color_note_button(newButton[0], newButton[1], scaleNoteNumber, True) self._pressed_notes.append(midiNote) if self.debugging: - print "Button", buttonNumber, "pressed with MIDI note number", midiNote, "and velocity", velocity + print ("Button", buttonNumber, "pressed with MIDI note number", midiNote, "and velocity", velocity) pass # print "Pressed Notes", _pressed_notes return @@ -450,7 +450,7 @@ def _grid_musical_mode_button_pressed(self, x, y): index = (x - 1) + ((4 - y) * 8) self._grid_musical_mode = self.MUSICAL_MODES.keys()[index] if self.debugging: - print "Musical mode is", self._grid_musical_mode + print("Musical mode is", self._grid_musical_mode) pass self._all_buttons_released() From 21f96e44c2ae6e4e70401c26aef30f584c50072c Mon Sep 17 00:00:00 2001 From: Alberto Fanjul Date: Fri, 25 Mar 2022 20:36:01 +0100 Subject: [PATCH 05/13] apply floor correctly --- grid_instrument/grid_instrument.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grid_instrument/grid_instrument.py b/grid_instrument/grid_instrument.py index 9813251..8f42d00 100644 --- a/grid_instrument/grid_instrument.py +++ b/grid_instrument/grid_instrument.py @@ -375,8 +375,8 @@ def _get_buttons_for_midi_note(self, midiNote): def get_currently_playing_midi_notes(self): midiNotes = [] for buttonNumber in self._pressed_buttons: - x = int(math.floor(buttonNumber % 8)) + 1 - y = (buttonNumber / 8) + 1 + x = int(buttonNumber % 8) + 1 + y = math.floor(buttonNumber / 8) + 1 noteInfo = self._get_note_info(x, y) if noteInfo[0] not in midiNotes: midiNotes.append(noteInfo[0]) From 9977c5a0bdfb9a289ff2635dac7c58c4eb96ebf4 Mon Sep 17 00:00:00 2001 From: Alberto Fanjul Date: Fri, 25 Mar 2022 20:36:46 +0100 Subject: [PATCH 06/13] modifications to use python3 rtmidi --- play.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/play.py b/play.py index 412d93e..32dc21d 100755 --- a/play.py +++ b/play.py @@ -15,13 +15,13 @@ def note_callback(messageType, midiNote, velocity): if messageType is "note_on": - midiout.send_message([0x90, midiNote, velocity]) + midiout.sendMessage(rtmidi.MidiMessage.noteOn(0x90, midiNote, velocity)) elif messageType is "note_off": - midiout.send_message([0x80, midiNote, velocity]) + midiout.sendMessage(rtmidi.MidiMessage.noteOff(0x80, midiNote)) # Create a MIDI output port -midiout = rtmidi.MidiOut() -midiout.open_virtual_port("Grid Instrument (Virtual Port)") +midiout = rtmidi.RtMidiOut() +midiout.openVirtualPort("Grid Instrument (Virtual Port)") # Set up GridInstrument instrument = grid_instrument.GridInstrument() From 0eb1ce0ec9e35e2e738d892cfa133afce685d8ca Mon Sep 17 00:00:00 2001 From: Alberto Fanjul Date: Fri, 25 Mar 2022 20:37:13 +0100 Subject: [PATCH 07/13] whitespace --- grid_instrument/grid_instrument.py | 20 ++++++++++---------- play.py | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/grid_instrument/grid_instrument.py b/grid_instrument/grid_instrument.py index 8f42d00..efaf31d 100644 --- a/grid_instrument/grid_instrument.py +++ b/grid_instrument/grid_instrument.py @@ -50,10 +50,10 @@ class GridInstrument: NOTE_NAMES = ["C", "C#", "D", "Eb", "E", "F", "F#", "G", "G#", "A", "A#", "B"] - NOTE_COLORS = { - "Mk1": { - "pressed": [0, 63], - "root": [3, 0], + NOTE_COLORS = { + "Mk1": { + "pressed": [0, 63], + "root": [3, 0], "noteInScale": [1, 1], "noteOutOfScale": [0, 0], "settingsKeyOff": [0, 4], @@ -65,10 +65,10 @@ class GridInstrument: "settingsGridLayoutOff": [1, 0], "settingsGridLayoutOn": [3, 0], - }, - "Mk2": { - "pressed": [0, 50, 0], - "root": [0, 10, 30], + }, + "Mk2": { + "pressed": [0, 50, 0], + "root": [0, 10, 30], "noteInScale": [10, 10, 15], "noteOutOfScale": [0, 0, 0], "settingsKeyOff": [0, 4, 0], @@ -160,7 +160,7 @@ def _main_loop(self): if randomButtonModeEnabled: if randomButtonCounter > 30: if randomButton: - self._button_released(randomButton[0], randomButton[1]) + self._button_released(randomButton[0], randomButton[1]) randomButton = None # Make a new randomButton randomButton = [random.randint(1,8), random.randint(1,8)] @@ -403,7 +403,7 @@ def _button_pressed(self, x, y, velocity): # print "Pressed Notes", _pressed_notes return - # Todo, we should actually + # Todo, we should actually def _all_buttons_released(self): for midiNote in self._pressed_notes: self.note_callback('note_off', midiNote, 0) diff --git a/play.py b/play.py index 32dc21d..9d7af25 100755 --- a/play.py +++ b/play.py @@ -32,4 +32,4 @@ def note_callback(messageType, midiNote, velocity): instrument.max_velocity = 100 instrument.default_velocity = 100 -instrument.start() \ No newline at end of file +instrument.start() From 9cc6f43340e29f768b563436cc2020cf25749dc1 Mon Sep 17 00:00:00 2001 From: Alberto Fanjul Date: Fri, 25 Mar 2022 20:37:31 +0100 Subject: [PATCH 08/13] Show all supported devices --- grid_instrument/grid_instrument.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grid_instrument/grid_instrument.py b/grid_instrument/grid_instrument.py index efaf31d..1dc35d9 100644 --- a/grid_instrument/grid_instrument.py +++ b/grid_instrument/grid_instrument.py @@ -115,7 +115,7 @@ def discover_launchpad(self, keep_checking=False): # create an instance self.lp = launchpad.Launchpad() while self._launchpad_model is None: - # lp.ListAll() + self.lp.ListAll() # check what we have here and override lp if necessary if self.lp.Check( 0, "pro" ): self.lp = launchpad.LaunchpadPro() From 9f6895a47fff947cae2058cb558641ff3d45dce8 Mon Sep 17 00:00:00 2001 From: Alberto Fanjul Date: Fri, 25 Mar 2022 20:37:49 +0100 Subject: [PATCH 09/13] Control unimplemented functions --- grid_instrument/grid_instrument.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grid_instrument/grid_instrument.py b/grid_instrument/grid_instrument.py index 1dc35d9..6a0d6fc 100644 --- a/grid_instrument/grid_instrument.py +++ b/grid_instrument/grid_instrument.py @@ -210,7 +210,7 @@ def _main_loop(self): print("Key is ", self.NOTE_NAMES[self._grid_key]) elif (1 <= x <= 8) and (1 <= y <= 4): self._grid_musical_mode_button_pressed(x, y) - if x in [1, 2] and y == 9 and pressed and (self.kid_mode is not True): + if x in [1, 2] and y == 9 and pressed and (self.kid_mode is not True) and self.func_button_callback: self.func_button_callback(x, y, pressed) elif x is 9 and y == 8: if pressed: From 25839e46870244eb9704f15063ae0c0ae98d40d0 Mon Sep 17 00:00:00 2001 From: Alberto Fanjul Date: Fri, 25 Mar 2022 20:41:43 +0100 Subject: [PATCH 10/13] allow all files to be under vcs control and ignore cache compilation --- .gitignore | 15 +-------------- examples/.gitignore | 6 ------ 2 files changed, 1 insertion(+), 20 deletions(-) delete mode 100644 examples/.gitignore diff --git a/.gitignore b/.gitignore index 1c53385..bee8a64 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1 @@ -* - -!.gitignore -!/images -!/images/* -!/examples -!/examples/* -!/grid_instrument -!/grid_instrument/* -!play.py -!README.md -!MANIFEST.in -!LICENSE.txt -!setup.py +__pycache__ diff --git a/examples/.gitignore b/examples/.gitignore deleted file mode 100644 index 2efe3d6..0000000 --- a/examples/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -* - -!.gitignore -!simple.py -!threading.py -!midi_output.py From 94b6886f10beae3d13011b7817b3225fd543cb86 Mon Sep 17 00:00:00 2001 From: Alberto Fanjul Date: Fri, 25 Mar 2022 21:25:11 +0100 Subject: [PATCH 11/13] Apply fixes on examples --- examples/{threading.py => async.py} | 9 +++++---- examples/midi_output.py | 13 +++++++------ examples/simple.py | 9 +++++---- setup.py | 10 +++++----- 4 files changed, 22 insertions(+), 19 deletions(-) rename examples/{threading.py => async.py} (79%) mode change 100644 => 100755 mode change 100644 => 100755 examples/midi_output.py mode change 100644 => 100755 examples/simple.py diff --git a/examples/threading.py b/examples/async.py old mode 100644 new mode 100755 similarity index 79% rename from examples/threading.py rename to examples/async.py index 49cc110..dbbb427 --- a/examples/threading.py +++ b/examples/async.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # # Quick usage example of "grid_instrument" with threading. # Works with all Launchpads: Mk1, Mk2, S/Mini, Pro, XL and LaunchKey @@ -9,15 +9,16 @@ # import grid_instrument +from grid_instrument import grid_instrument import threading import time def note_callback(messageType, midiNote, velocity): - print "Note callback. messageType=", messageType, midiNote, velocity + print("Note callback. messageType=", messageType, midiNote, velocity) def button_callback(x, y, pressed): - print "Button Callback. x=", x, ", y=", y, ", pressed=", pressed + print("Button Callback. x=", x, ", y=", y, ", pressed=", pressed) instrument = grid_instrument.GridInstrument() @@ -37,4 +38,4 @@ def button_callback(x, y, pressed): while True: time.sleep(2) - pass \ No newline at end of file + pass diff --git a/examples/midi_output.py b/examples/midi_output.py old mode 100644 new mode 100755 index 1fe8abe..d55104c --- a/examples/midi_output.py +++ b/examples/midi_output.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # # Quick usage example of "grid_instrument" with MIDI output port. # Works with all Launchpads: Mk1, Mk2, S/Mini, Pro, XL and LaunchKey @@ -9,21 +9,22 @@ # import grid_instrument +from grid_instrument import grid_instrument import rtmidi import time def note_callback(messageType, midiNote, velocity): if messageType is "note_on": - midiout.send_message([0x90, midiNote, velocity]) + midiout.sendMessage(rtmidi.MidiMessage.noteOn(0x90, midiNote, velocity)) elif messageType is "note_off": - midiout.send_message([0x80, midiNote, velocity]) + midiout.sendMessage(rtmidi.MidiMessage.noteOff(0x80, midiNote)) # Create a MIDI output port -midiout = rtmidi.MidiOut() -midiout.open_virtual_port("Grid Instrument (Virtual Port)") +midiout = rtmidi.RtMidiOut() +midiout.openVirtualPort("Grid Instrument (Virtual Port)") # Set up GridInstrument instrument = grid_instrument.GridInstrument() instrument.intro_message = 'grid' instrument.note_callback = note_callback -instrument.start() \ No newline at end of file +instrument.start() diff --git a/examples/simple.py b/examples/simple.py old mode 100644 new mode 100755 index fab14ee..6d26c61 --- a/examples/simple.py +++ b/examples/simple.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # # Quick usage example of "grid_instrument". # Works with all Launchpads: Mk1, Mk2, S/Mini, Pro, XL and LaunchKey @@ -9,14 +9,15 @@ # import grid_instrument +from grid_instrument import grid_instrument import threading def note_callback(messageType, midiNote, velocity): - print "Note callback. messageType=", messageType, midiNote, velocity + print("Note callback. messageType=", messageType, midiNote, velocity) def button_callback(x, y, pressed): - print "Button Callback. x=", x, ", y=", y, ", pressed=", pressed + print("Button Callback. x=", x, ", y=", y, ", pressed=", pressed) instrument = grid_instrument.GridInstrument() @@ -29,4 +30,4 @@ def button_callback(x, y, pressed): instrument.note_callback = note_callback # set the callback for function buttons instrument.func_button_callback = button_callback -instrument.start() \ No newline at end of file +instrument.start() diff --git a/setup.py b/setup.py index 0c9d138..ab5e3ce 100644 --- a/setup.py +++ b/setup.py @@ -1,19 +1,19 @@ from setuptools import setup import sys -if not sys.version_info[0] == 2: - sys.exit("Error: grid_instrument requires Python 2") +if not sys.version_info[0] == 3: + sys.exit("Error: grid_instrument requires Python 3") setup( name = "grid_instrument", - version = "0.6.2", + version = "0.7.0", description = "Turn your Novation Launchpad into a MIDI instrument.", - long_description = open('README.rst').read(), + long_description = open('README.md').read(), author = "Dave Hilowitz", author_email = "dhilowitz@gmail.com", license = "MIT License", keywords = "novation launchpad scales midi", url = "https://github.com/dhilowitz/GridInstrument", packages = ["grid_instrument"], - install_requires = ["launchpad_rtmidi_py", "python-rtmidi"] + install_requires = ["launchpad_py", "rtmidi"] ) From 7bca5e8bb8c4649757ce1455c7ec6bd4c1378e1a Mon Sep 17 00:00:00 2001 From: Alberto Fanjul Date: Fri, 25 Mar 2022 21:32:15 +0100 Subject: [PATCH 12/13] Organize examples and project info --- README.md | 10 ++++++---- examples/midi_output.py | 7 ++++++- play.py | 35 ----------------------------------- 3 files changed, 12 insertions(+), 40 deletions(-) delete mode 100755 play.py diff --git a/README.md b/README.md index 98929aa..c8fd26c 100644 --- a/README.md +++ b/README.md @@ -28,11 +28,13 @@ Before you try to do anything, make sure you have **Python 2** and **pip** insta Download the source code from github and install prerequisites: git clone https://github.com/dhilowitz/GridInstrument - cd GridInstrument; pip install launchpad_rtmidi_py + cd GridInstrument + pip install . -Run the app: +Run the examples: - python play.py + cd examples + ./midi_output.py If all goes well, you should see your grid light up. Next, go into another piece of software that can receive MIDI signals (sforzando is a good, free choice), and you should see a new MIDI device called "Grid Instrument (Virtual Port)" @@ -53,4 +55,4 @@ Install it: #### Option 2: Install it with Pip - pip install grid_instrument \ No newline at end of file + pip install grid_instrument diff --git a/examples/midi_output.py b/examples/midi_output.py index d55104c..9d7af25 100755 --- a/examples/midi_output.py +++ b/examples/midi_output.py @@ -4,7 +4,7 @@ # Works with all Launchpads: Mk1, Mk2, S/Mini, Pro, XL and LaunchKey # # -# David Hilowitz 9/24/17 +# David Hilowitz 1/15/19 # decided.ly / davehilowitz.com # @@ -27,4 +27,9 @@ def note_callback(messageType, midiNote, velocity): instrument = grid_instrument.GridInstrument() instrument.intro_message = 'grid' instrument.note_callback = note_callback +instrument.launchpad_pro_velocity_multiplier = 2.5 +instrument.min_velocity = 100 +instrument.max_velocity = 100 +instrument.default_velocity = 100 + instrument.start() diff --git a/play.py b/play.py deleted file mode 100755 index 9d7af25..0000000 --- a/play.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python -# -# Quick usage example of "grid_instrument" with MIDI output port. -# Works with all Launchpads: Mk1, Mk2, S/Mini, Pro, XL and LaunchKey -# -# -# David Hilowitz 1/15/19 -# decided.ly / davehilowitz.com -# - -import grid_instrument -from grid_instrument import grid_instrument -import rtmidi -import time - -def note_callback(messageType, midiNote, velocity): - if messageType is "note_on": - midiout.sendMessage(rtmidi.MidiMessage.noteOn(0x90, midiNote, velocity)) - elif messageType is "note_off": - midiout.sendMessage(rtmidi.MidiMessage.noteOff(0x80, midiNote)) - -# Create a MIDI output port -midiout = rtmidi.RtMidiOut() -midiout.openVirtualPort("Grid Instrument (Virtual Port)") - -# Set up GridInstrument -instrument = grid_instrument.GridInstrument() -instrument.intro_message = 'grid' -instrument.note_callback = note_callback -instrument.launchpad_pro_velocity_multiplier = 2.5 -instrument.min_velocity = 100 -instrument.max_velocity = 100 -instrument.default_velocity = 100 - -instrument.start() From 6b2dd97bf0d5e955151827c3e19672e65af8ec6e Mon Sep 17 00:00:00 2001 From: Alberto Fanjul Date: Fri, 25 Mar 2022 22:10:46 +0100 Subject: [PATCH 13/13] Change musical mode --- grid_instrument/grid_instrument.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/grid_instrument/grid_instrument.py b/grid_instrument/grid_instrument.py index 6a0d6fc..f8e3f79 100644 --- a/grid_instrument/grid_instrument.py +++ b/grid_instrument/grid_instrument.py @@ -448,10 +448,11 @@ def _button_released(self, x, y): def _grid_musical_mode_button_pressed(self, x, y): index = (x - 1) + ((4 - y) * 8) - self._grid_musical_mode = self.MUSICAL_MODES.keys()[index] - if self.debugging: - print("Musical mode is", self._grid_musical_mode) - pass + modes = list(self.MUSICAL_MODES.keys()) + if index < len(modes): + self._grid_musical_mode = modes[index] + if self.debugging: + print("Musical mode is", self._grid_musical_mode) self._all_buttons_released() self._color_buttons()