@@ -2934,3 +2934,207 @@ def Reset( self ):
2934
2934
# Also, setting the brightness to 0/off might cause additional trouble.
2935
2935
# self.LedAllOn( 0 )
2936
2936
pass
2937
+
2938
+ ########################################################################################
2939
+ ### CLASS LaunchpadPROMk3
2940
+ ###
2941
+ ### For 3-color "X" Launchpads
2942
+ ########################################################################################
2943
+ # +---+ +---+---+---+---+---+---+---+---+ +---+
2944
+ # | 90| | 91| | | | | | | 98| | 99|
2945
+ # +---+ +---+---+---+---+---+---+---+---+ +---+
2946
+ #
2947
+ # +---+ +---+---+---+---+---+---+---+---+ +---+
2948
+ # | 80| | 81| | | | | | | | | 89|
2949
+ # +---+ +---+---+---+---+---+---+---+---+ +---+
2950
+ # | 70| | | | | | | | | | | 79|
2951
+ # +---+ +---+---+---+---+---+---+---+---+ +---+
2952
+ # | 60| | | | | | | | 67| | | 69|
2953
+ # +---+ +---+---+---+---+---+---+---+---+ +---+
2954
+ # | 50| | | | | | | | | | | 59|
2955
+ # +---+ +---+---+---+---+---+---+---+---+ +---+
2956
+ # | 40| | | | | | | | | | | 49|
2957
+ # +---+ +---+---+---+---+---+---+---+---+ +---+
2958
+ # | 30| | | | | | | | | | | 39|
2959
+ # +---+ +---+---+---+---+---+---+---+---+ +---+
2960
+ # | 20| | | | 23| | | | | | | 29|
2961
+ # +---+ +---+---+---+---+---+---+---+---+ +---+
2962
+ # | 10| | | | | | | | | | | 19|
2963
+ # +---+ +---+---+---+---+---+---+---+---+ +---+
2964
+ #
2965
+ # +---+---+---+---+---+---+---+---+
2966
+ # |101|102| | | | | |108|
2967
+ # +---+---+---+---+---+---+---+---+
2968
+ # +---+---+---+---+---+---+---+---+
2969
+ # | 1| 2| | | | | | 8|
2970
+ # +---+---+---+---+---+---+---+---+
2971
+ class LaunchpadProMk3 ( LaunchpadPro ):
2972
+
2973
+ # COLORS = {'black':0, 'off':0, 'white':3, 'red':5, 'green':17 }
2974
+
2975
+ #-------------------------------------------------------------------------------------
2976
+ #-- Opens one of the attached Launchpad MIDI devices.
2977
+ #-- Uses search string "ProMK3", by default.
2978
+ #-------------------------------------------------------------------------------------
2979
+ # Overrides "LaunchpadPro" method
2980
+ # TODO: Find a fix for the two ProMk3 MIDI devices
2981
+ def Open ( self , number = 0 , name = "ProMk3" ):
2982
+ retval = super ( LaunchpadProMk3 , self ).Open ( number = number , name = name )
2983
+ if retval == True :
2984
+ self .LedSetMode ( 1 )
2985
+
2986
+ return retval
2987
+
2988
+
2989
+ #-------------------------------------------------------------------------------------
2990
+ #-- Checks if a device exists, but does not open it.
2991
+ #-- Does not check whether a device is in use or other, strange things...
2992
+ #-- Uses search string "ProMk3", by default.
2993
+ #-------------------------------------------------------------------------------------
2994
+ # Overrides "LaunchpadBase" method
2995
+ def Check ( self , number = 0 , name = "ProMk3" ):
2996
+ return super ( LaunchpadProMk3 , self ).Check ( number = number , name = name )
2997
+
2998
+
2999
+ #-------------------------------------------------------------------------------------
3000
+ #-- Sets the button layout (and codes) to the set, specified by <mode>.
3001
+ #-- Valid options:
3002
+ #-- 00 - Session, 01 - Fader, 02 - Chord, 03 - Custom Mode,
3003
+ #-- 04 - Note / Drum, 05 - Scale Settings, 06 - Sequencer Settings, 07 - Sequencer Steps,
3004
+ #-- 08 - Sequencer Velocity, 09 - Sequencer Pattern Settings, 0A - Sequencer Probability, 0B - Sequencer Mutation,
3005
+ #-- 0C - Sequencer Micro Step, 0D - Sequencer Projects, 0E - Sequencer Patterns, 0F - Sequencer Tempo,
3006
+ #-- 10 - Sequencer Swing, 11 - Programmer Mode, 12 - Settings Menu, 13 - Custom mode Settings,
3007
+ #-------------------------------------------------------------------------------------
3008
+ # TODO: ASkr, Undocumented!
3009
+ # TODO: return value
3010
+ def LedSetLayout ( self , mode ):
3011
+ ValidModes = [0x00 , 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 , 0x08 , 0x09 , 0x0A , 0x0B , 0x0C , 0x0D , 0x0E , 0x0F , 0x10 , 0x11 , 0x12 , 0x13 ]
3012
+ if mode not in ValidModes :
3013
+ return
3014
+
3015
+ self .midi .RawWriteSysEx ( [ 0 , 32 , 41 , 2 , 14 , 0 , mode ] )
3016
+ time .wait (10 )
3017
+
3018
+
3019
+ #-------------------------------------------------------------------------------------
3020
+ #-- Selects the ProMk3's mode.
3021
+ #-- <mode> -> 0 -> "Ableton Live mode"
3022
+ #-- 1 -> "Programmer mode" (what we need)
3023
+ #-------------------------------------------------------------------------------------
3024
+ def LedSetMode ( self , mode ):
3025
+ if mode < 0 or mode > 1 :
3026
+ return
3027
+
3028
+ self .midi .RawWriteSysEx ( [ 0 , 32 , 41 , 2 , 14 , 14 , mode ] )
3029
+ time .wait (10 )
3030
+
3031
+
3032
+ #-------------------------------------------------------------------------------------
3033
+ #-- Sets the button layout to "Session" mode.
3034
+ #-------------------------------------------------------------------------------------
3035
+ # TODO: ASkr, Undocumented!
3036
+ def LedSetButtonLayoutSession ( self ):
3037
+ self .LedSetLayout ( 0 )
3038
+
3039
+
3040
+ #-------------------------------------------------------------------------------------
3041
+ #-- Controls a grid LED by its position <number> and a color, specified by
3042
+ #-- <red>, <green> and <blue> intensities, with can each be an integer between 0..63.
3043
+ #-- If <blue> is omitted, this methos runs in "Classic" compatibility mode and the
3044
+ #-- intensities, which were within 0..3 in that mode, are multiplied by 21 (0..63)
3045
+ #-- to emulate the old brightness feeling :)
3046
+ #-- Notice that each message requires 10 bytes to be sent. For a faster, but
3047
+ #-- unfortunately "not-RGB" method, see "LedCtrlRawByCode()"
3048
+ #-- ProMk3 color data extended to 7-bit but for compatibility we still using 6-bit values
3049
+ #-------------------------------------------------------------------------------------
3050
+ def LedCtrlRaw ( self , number , red , green , blue = None ):
3051
+
3052
+ if number < 0 or number > 99 :
3053
+ return
3054
+
3055
+ if blue is None :
3056
+ blue = 0
3057
+ red *= 21
3058
+ green *= 21
3059
+
3060
+ limit = lambda n , mini , maxi : max (min (maxi , n ), mini )
3061
+
3062
+ red = limit ( red , 0 , 63 ) << 1
3063
+ green = limit ( green , 0 , 63 ) << 1
3064
+ blue = limit ( blue , 0 , 63 ) << 1
3065
+
3066
+ self .midi .RawWriteSysEx ( [ 0 , 32 , 41 , 2 , 14 , 3 , 3 , number , red , green , blue ] )
3067
+
3068
+
3069
+ #-------------------------------------------------------------------------------------
3070
+ #-- Same as LedCtrlRawByCode, but with a pulsing LED.
3071
+ #-- Pulsing can be stoppped by another Note-On/Off or SysEx message.
3072
+ #-------------------------------------------------------------------------------------
3073
+ def LedCtrlPulseByCode ( self , number , colorcode = None ):
3074
+
3075
+ if number < 0 or number > 99 :
3076
+ return
3077
+
3078
+ if colorcode is None :
3079
+ colorcode = LaunchpadPro .COLORS ['white' ]
3080
+
3081
+ colorcode = min (127 , max (0 , colorcode ))
3082
+
3083
+ self .midi .RawWrite ( 146 , number , colorcode )
3084
+
3085
+
3086
+ #-------------------------------------------------------------------------------------
3087
+ #-- Same as LedCtrlPulseByCode, but with a dual color flashing LED.
3088
+ #-- The first color is the one that is already enabled, the second one is the
3089
+ #-- <colorcode> argument in this method.
3090
+ #-- Flashing can be stoppped by another Note-On/Off or SysEx message.
3091
+ #-------------------------------------------------------------------------------------
3092
+ def LedCtrlFlashByCode ( self , number , colorcode = None ):
3093
+
3094
+ if number < 0 or number > 99 :
3095
+ return
3096
+
3097
+ if colorcode is None :
3098
+ colorcode = LaunchpadPro .COLORS ['white' ]
3099
+
3100
+ colorcode = min (127 , max (0 , colorcode ))
3101
+
3102
+ self .midi .RawWrite ( 145 , number , colorcode )
3103
+
3104
+
3105
+ #-------------------------------------------------------------------------------------
3106
+ #-- Quickly sets all all LEDs to the same color, given by <colorcode>.
3107
+ #-- If <colorcode> is omitted, "white" is used.
3108
+ #-------------------------------------------------------------------------------------
3109
+ def LedAllOn ( self , colorcode = None ):
3110
+ if colorcode is None :
3111
+ colorcode = LaunchpadPro .COLORS ['white' ]
3112
+
3113
+ colorcode = min (127 , max (0 , colorcode ))
3114
+
3115
+ # TODO: Maybe the SysEx was indeed a better idea :)
3116
+ # Did some tests:
3117
+ # MacOS: doesn't matter;
3118
+ # Windoze: SysEx much better;
3119
+ # Linux: completely freaks out
3120
+ for x in range (9 ):
3121
+ for y in range (9 ):
3122
+ self .midi .RawWrite (144 , (x + 1 ) + ((y + 1 ) * 10 ), colorcode )
3123
+
3124
+
3125
+ #-------------------------------------------------------------------------------------
3126
+ #-- (fake to) reset the Launchpad
3127
+ #-- Turns off all LEDs
3128
+ #-------------------------------------------------------------------------------------
3129
+ def Reset ( self ):
3130
+ self .LedAllOn ( 0 )
3131
+
3132
+
3133
+ #-------------------------------------------------------------------------------------
3134
+ #-- Go back to custom modes before closing connection
3135
+ #-- Otherwise Launchpad will stuck in programmer mode
3136
+ #-------------------------------------------------------------------------------------
3137
+ def Close ( self ):
3138
+ # TODO: redundant (but needs fix for Py2 embedded anyway)
3139
+ self .midi .CloseInput ()
3140
+ self .midi .CloseOutput ()
0 commit comments