diff --git a/README.md b/README.md index 5ef62d2..f806a8d 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,10 @@ Now with full [Midi Fighter 64][23] support (8/2020). Finally! Hehe, say hello to the [Mk3 Pro][24] (8/2020) +And here comes the [Midi Fighter 3D][27] (5/2021) + --- -## STATUS 2021/01/xx: +## STATUS 2021/11/xx: ### Devices @@ -40,11 +42,11 @@ Finally! Hehe, say hello to the [Mk3 Pro][24] (8/2020) Launchpad Pro - class "LaunchpadPro()" LEDs and buttons (digitally only (yet)) - Launchpad Pro Mk3 - class "LaunchpadProMk3()" EXPERIMENTAL+++ as in "should be really ok" + Launchpad Pro Mk3 - class "LaunchpadProMk3()" LEDs and buttons, pressure, everything; "should work" Launchpad Mini Mk3 - class "LaunchpadMiniMk3()" LEDs and buttons *** RENAMED 5/2020 *** - Launchpad X - class "LaunchpadLPX()" EXPERIMENTAL+++ as in "should work really well" + Launchpad X - class "LaunchpadLPX()" LEDs and buttons and more Launch Control - class "LaunchControl()" EXPERIMENTAL @@ -56,6 +58,8 @@ Finally! Hehe, say hello to the [Mk3 Pro][24] (8/2020) Midi Fighter 64 - class "MidiFighter64" LEDs and buttons + Midi Fighter 3D - class "MidiFighter3D IN WORK + > PRO MK3 USERS: > You need to disable the Launchpad's "Transmit Clock" in the MIDI settings! @@ -63,6 +67,9 @@ Finally! Hehe, say hello to the [Mk3 Pro][24] (8/2020) > > The Pro Mk3 needs the latest Firmware to operate flawlessly. FW is only available > via a Novation account- and product registration. +> +> Alternatively, visit [mat1jaczyyy's Firmware Utility][28] on a Chromium-based browser to update the firmware of Pro Mk3. +> USE THIS AT YOUR OWN RISK! Please notice that the class "LaunchpadMk3()" was renamed to "LaunchpadMiniMk3()" in 5/2020. This was necessary to avoid confusion with the device search string and the new "Pro-Mk3" Launchpad. @@ -86,6 +93,17 @@ Successfully tested with Ubuntu 18.04-LTS+. Requires compiling your own PyGame t --- ## NEWS +### CHANGES 2021/05/XX: + - fixed Launchpad Mk1 code in buttons_raw.py demo; thx to jmtrivial + - added first Midi Fighter 3D code; derived from the MF64 + - added MF3D LedCtrlRaw() + - added MF3D ButtonStateRaw() + - added MF3D LedCtrlXY() + +### CHANGES 2021/04/XX: + - added link to driver for Mk1 Launchpad and Mini + - fixed Mk1 Automap buttons always yellow; thx to mutax and Ferada + ### CHANGES 2021/01/XX: - fix for Python 3.9 - updated documentation for raw LED and button codes (top row had wrong values) @@ -755,6 +773,11 @@ name it once shipped the first red/green LED with! ### For Launchpad Mk1 users (the original "Classic" Launchpad): + Also valid for the Mk1 Mini. + + (Most likely still) requires an USB driver for Windoze (7/10/...). + Look out for the Novation [USB Driver 2.xx][26]. + USE CLASS "Launchpad": lp = launchpad.Launchpad() @@ -1173,7 +1196,7 @@ Functions requiring a color code have a "...ByCode" naming style. --- -## Midi Fighter 64 class methods overview +## Midi Fighter 64 and Midi Fighter 3D class methods overview *WORK IN PROGESS* @@ -1201,7 +1224,6 @@ There is no possibility to control the RGB LEDs individually. ![RGB color palette](/images/mf64_colorcodes.png) - --- ## Detailed description of common Launchpad methods @@ -2377,8 +2399,8 @@ There is no possibility to control the RGB LEDs individually. PARAMS: RETURN: [ ] An empty list if no event occured, otherwise... [ , , ] ... a list with three fields: - 0..7; x coordinate of button - 0..7; y coordinate of button + 0..7; x coordinate of button (0..3 for Midi Fighter 3D) + 0..7; y coordinate of button (0..3 for Midi Fighter 3D) >0 = pressed; 0 = released @@ -2415,6 +2437,7 @@ There is no possibility to control the RGB LEDs individually. MODE_ANIM_TRIANGLE PARAMS: 36..99; number of the LED to control + see tables at end of file 0..127; color code [OPTIONAL] 18..53, see above RETURN: @@ -2449,6 +2472,7 @@ There is no possibility to control the RGB LEDs individually. MODE_ANIM_TRIANGLE PARAMS: 36..99; number of the LED to control + see tables at end of file 18..53; see above RETURN: @@ -2459,14 +2483,16 @@ There is no possibility to control the RGB LEDs individually. See table with coordinates at the end of this document. Color codes are somewhere above (see image). - PARAMS: 0..7; x coordinate - 0..7; y coordinate + PARAMS: 0..7; x coordinate (0..3 for Midi Fighter 3D) + 0..7; y coordinate (0..3 for Midi Fighter 3D) 0..127; color code RETURN: ### LedCtrlChar( char, color, [offsx = 0], [offsy = 0], [coloroff = 0] ) + Only for Midi Fighter 64! + Displays character with a color of and a lateral offset of (-8..8) on the Midi Fighter. does not have yet any function. @@ -2496,6 +2522,8 @@ There is no possibility to control the RGB LEDs individually. ### LedCtrlString( string, color, [coloroff = 0], [direction = 0], [waitms = 150] ) + Only for Midi Fighter 64! + Scrolls across the Midi Fighter's 8x8 matrix. specifies the color of the string and the background. determines the direction of scrolling. @@ -3144,6 +3172,62 @@ The mode keys return: +--- +## (TODO) Led and Button codes, Midi Fighter 3D + +### RAW Mode + + Button and LED codes depend on the selected bank, the bottom row with the small buttons. + Selected bank is indicated with a ```#x#``` here. + + Notice that the side button codes 36-40 might overlap with the arcade buttons. + This behaviour can be reprogrammed with the Midi Fighter Utility. + + +---+---+---+---+ +---+---+---+---+ + | 39| | | 36| | 55| | | 52| + +---+ +---+---+---+---+ +---+ +---+ +---+---+---+---+ +---+ + | 23| | 43| | | 40| | 20| | 29| | 59| | | 56| | 26| + | 24| +---+---+---+---+ | 21| | 30| +---+---+---+---+ | 27| + | 25| | 47| | | 44| | 22| | 31| | 63| | | 60| | 28| + +---+ +---+---+---+---+ +---+ +---+ +---+---+---+---+ +---+ + | 51| | | 48| | 67| | | 64| + +---+---+---+---+ +---+---+---+---+ + +---+---+---+---+ +---+---+---+---+ + | 3 | 2 | 1 |#0#| | 3 | 2 |#1#| 0 | + +---+---+---+---+ +---+---+---+---+ + + +---+---+---+---+ +---+---+---+---+ + | 71| | | 68| | 87| | | 84| + +---+ +---+---+---+---+ +---+ +---+ +---+---+---+---+ +---+ + | 35| | 75| | | 72| | 32| | 41| | 91| | | 88| | 38| + | 36| +---+---+---+---+ | 33| | 42| +---+---+---+---+ | 39| + | 37| | 79| | | 76| | 34| | 43| | 95| | | 92| | 40| + +---+ +---+---+---+---+ +---+ +---+ +---+---+---+---+ +---+ + | 83| | | 80| | 99| | | 96| + +---+---+---+---+ +---+---+---+---+ + +---+---+---+---+ +---+---+---+---+ + | 3 |#2#| 1 | 0 | |#3#| 2 | 1 | 0 | + +---+---+---+---+ +---+---+---+---+ + + +### XY MODE + + 0 1 2 3 + +---+---+---+---+ + 0 | |1/0| | | 0 + +---+ +---+---+---+---+ +---+ + 1 | | | | | | | | | 1 + | | +---+---+---+---+ | | + 2 | | | | | |3/2| | | 2 + +---+ +---+---+---+---+ +---+ + 3 |0/3| | | | 3 + +---+---+---+---+ + +---+---+---+---+ + | | | | | + +---+---+---+---+ + + + --- Have fun FMMT666(ASkr) @@ -3175,3 +3259,6 @@ FMMT666(ASkr) [23]: https://twitter.com/FMMT666/status/1299842680533463043 [24]: https://twitter.com/FMMT666/status/1299478117497688073 [25]: https://www.midifighter.com/ +[26]: https://customer.novationmusic.com/en/support/downloads?brand=Novation&product_by_type=510&download_type=all +[27]: https://twitter.com/FMMT666/status/1390806661829386241 +[28]: https://fw.mat1jaczyyy.com diff --git a/examples/buttons_raw.py b/examples/buttons_raw.py index 346d2d4..e17b81d 100644 --- a/examples/buttons_raw.py +++ b/examples/buttons_raw.py @@ -2,10 +2,10 @@ # # Quick button test. # Works with these Launchpads: Mk1, Mk2, Mini Mk3, S/Mini, Pro, Pro Mk3 -# And these: Midi Figther 64 +# And these: Midi Fighter 64, Mifi Fighter 3D # # -# FMMT666(ASkr) 7/2013..8/2020 +# FMMT666(ASkr) 7/2013..5/2021 # www.askrprojects.net # @@ -80,7 +80,14 @@ def main(): print("Midi Fighter 64") mode = "F64" + elif launchpad.MidiFighter3D().Check( 0 ): + lp = launchpad.MidiFighter3D() + if lp.Open( 0 ): + print("Midi Fighter 3D") + mode = "F3D" + else: + lp = launchpad.Launchpad() if lp.Open(): print("Launchpad Mk1/S/Mini") mode = "Mk1" diff --git a/launchpad_py/__init__.py b/launchpad_py/__init__.py index fa730a4..254a25c 100644 --- a/launchpad_py/__init__.py +++ b/launchpad_py/__init__.py @@ -9,5 +9,6 @@ from launchpad_py.launchpad import LaunchpadMiniMk3 from launchpad_py.launchpad import LaunchpadLPX from launchpad_py.launchpad import MidiFighter64 +from launchpad_py.launchpad import MidiFighter3D from launchpad_py.launchpad import LaunchpadProMk3 from launchpad_py import charset diff --git a/launchpad_py/launchpad.py b/launchpad_py/launchpad.py index dd8abed..72fd878 100644 --- a/launchpad_py/launchpad.py +++ b/launchpad_py/launchpad.py @@ -4,7 +4,7 @@ # # https://github.com/FMMT666/launchpad.py # -# FMMT666(ASkr) 01/2013..09/2019..08/2020..01/2021 +# FMMT666(ASkr) 01/2013..09/2019..08/2020..05/2021 # www.askrprojects.net # # @@ -204,11 +204,10 @@ def __del__( self ): #------------------------------------------------------------------------------------- def SearchDevices( self, name, output = True, input = True, quiet = True ): ret = [] - i = 0 - - for n in range( midi.get_count() ): - md = midi.get_device_info( n ) - if str( md[1].lower() ).find( name.lower() ) >= 0: + + for i in range( midi.get_count() ): + md = midi.get_device_info( i ) + if name.lower() in str( md[1].lower() ): if quiet == False: print('%2d' % ( i ), md) sys.stdout.flush() @@ -216,7 +215,6 @@ def SearchDevices( self, name, output = True, input = True, quiet = True ): ret.append( i ) if input == True and md[2] > 0: ret.append( i ) - i += 1 return ret @@ -511,12 +509,12 @@ def LedCtrlAutomap( self, number, red, green ): if number < 0 or number > 7: return - red = min( 0, red ) - red = max( 7, red ) - green = min( 0, green ) - green = max( 7, green ) + red = max( 0, red ) + red = min( 3, red ) + green = max( 0, green ) + green = min( 3, green ) led = self.LedGetColor( red, green ) - + self.midi.RawWrite( 176, 104 + number, led ) @@ -3096,6 +3094,138 @@ def Reset( self ): +######################################################################################## +### CLASS MidiFighter3D +### +### For Midi Fighter 3D Gedöns +######################################################################################## +class MidiFighter3D( MidiFighter64 ): + + # + # LED AND BUTTON NUMBERS IN RAW MODE + # + # Button codes depend on the selected bank, + # the bottom row with the small buttons. + # + # +---+---+---+---+ +---+---+---+---+ + # | 39| | | 36| | 55| | | 52| + # +---+ +---+---+---+---+ +---+ +---+ +---+---+---+---+ +---+ + # | | | 43| | | 40| | | | | | 59| | | 56| | | + # | | +---+---+---+---+ | | | | +---+---+---+---+ | | + # | | | 47| | | 44| | | | | | 63| | | 60| | | + # +---+ +---+---+---+---+ +---+ +---+ +---+---+---+---+ +---+ + # | 51| | | 48| | 67| | | 64| + # +---+---+---+---+ +---+---+---+---+ + # +---+---+---+---+ +---+---+---+---+ + # | | | |###| | | |###| | + # +---+---+---+---+ +---+---+---+---+ + # + # +---+---+---+---+ +---+---+---+---+ + # | 71| | | 68| | 87| | | 84| + # +---+ +---+---+---+---+ +---+ +---+ +---+---+---+---+ +---+ + # | | | 75| | | 72| | | | | | 91| | | 88| | | + # | | +---+---+---+---+ | | | | +---+---+---+---+ | | + # | | | 79| | | 76| | | | | | 95| | | 92| | | + # +---+ +---+---+---+---+ +---+ +---+ +---+---+---+---+ +---+ + # | 83| | | 80| | 99| | | 96| + # +---+---+---+---+ +---+---+---+---+ + # +---+---+---+---+ +---+---+---+---+ + # | |###| | | |###| | | | + # +---+---+---+---+ +---+---+---+---+ + # + # + # LED AND BUTTON NUMBERS IN XY MODE (X/Y) + # + # 0 1 2 3 + # +---+---+---+---+ + # 0 | |1/0| | | + # +---+ +---+---+---+---+ +---+ + # 1 | | | | | | | | | + # | | +---+---+---+---+ | | + # 2 | | | | | |3/2 | | | + # +---+ +---+---+---+---+ +---+ + # 3 |0/3| | | | + # +---+---+---+---+ + # +---+---+---+---+ + # | | | | | + # +---+---+---+---+ + + + #------------------------------------------------------------------------------------- + #-- Opens one of the attached Launchpad MIDI devices. + #-- Uses search string "Fighter 3D", by default. + #------------------------------------------------------------------------------------- + # Overrides "MidiFighter64" method + def Open( self, number = 0, name = "Fighter 3D" ): + return super( MidiFighter3D, self ).Open( number = number, name = name ) + + + #------------------------------------------------------------------------------------- + #-- Checks if a device exists, but does not open it. + #-- Does not check whether a device is in use or other, strange things... + #-- Uses search string "Fighter 3D", by default. + #------------------------------------------------------------------------------------- + # Overrides "MidiFighter64" method + def Check( self, number = 0, name = "Fighter 3D" ): + return super( MidiFighter3D, self ).Check( number = number, name = name ) + + + #------------------------------------------------------------------------------------- + #-- Returns the raw value of the last button change (pressed/unpressed) as a list + #-- [