diff --git a/device_FIRE-NFX.py b/device_FIRE-NFX.py index a479023..a1dc4f3 100644 --- a/device_FIRE-NFX.py +++ b/device_FIRE-NFX.py @@ -6,7 +6,7 @@ # develoment started: 11/24/2021 # first public beta: 07/13/2022 # -# thanks to: HDSQ, TayseteDj, CBaum83, DAWNLIGHT, Jaimezin, a candle, Miro and Image-Line +# thanks to: HDSQ, TayseteDj, CBaum83, MegaSix, rd3d2, DAWNLIGHT, Jaimezin, a candle, Miro and Image-Line # # @@ -42,7 +42,7 @@ # id = _thread.start_new_thread(task, (0,100)) # print('task started', id) -from harmonicScales import * +from fireNFX_HarmonicScales import * from fireNFX_DefaultSettings import * # from fireNFX_Classes import * from fireNFX_Defs import * @@ -347,17 +347,22 @@ def OnDirtyChannel(chan, flags): _DirtyChannelFlags = flags #print(chan, flags, _DirtyChannelFlags) +_lastFocus = -1 +widDict = { widMixer: 'Mixer', widChannelRack: 'Channel Rack', widPlaylist: 'PLaylist', widPianoRoll: 'Piano Roll', + widBrowser: 'Browser', widPlugin: 'Plugin', widPluginEffect: 'Plugin Effect', widPluginGenerator: 'Plugin Generator' + } + def OnRefresh(flags): global _PadMode global _isAltMode - #print('OnRefresh', flags) + global _lastFocus + print('OnRefresh', flags) if(flags == HW_CustomEvent_ShiftAlt): # called by HandleShiftAlt if(_ShiftHeld): RefreshShiftedStates() if(_DoubleTap): macShowScriptWindow.Execute() - #ShowScriptDebug() else: RefreshPadModeButtons() RefreshShiftAltButtons() @@ -366,9 +371,24 @@ def OnRefresh(flags): if(HW_Dirty_LEDs & flags): RefreshTransport() - UpdateWindowStates() - elif(HW_Dirty_FocusedWindow & flags): - UpdateWindowStates() + UpdateAndRefreshWindowStates() + + if(HW_Dirty_FocusedWindow & flags): + print('Focus changed') + formCap = ui.getFocusedFormCaption() + UpdateAndRefreshWindowStates() + if(_lastFocus in widDict.keys()): + print('=====> Changed to ', widDict[_lastFocus], formCap) + elif(_lastFocus == -1): + print('=====> None') + else: + slotIdx, uname, pname = GetActiveMixerEffectSlotInfo() + # if isKnownMixerEffect(): + # RefreshModes() + # GBMapTest() + # else: + # print("=====> FormCap ", formCap) + if(HW_Dirty_Performance & flags): # called when new channels or patterns added RefreshChannelStrip() @@ -464,6 +484,7 @@ def OnMidiIn(event): prevtime = _proctime _proctime = time.monotonic_ns() // 1000000 elapsed = _proctime-prevtime + if (_prevCtrlID == ctrlID): _DoubleTap = (elapsed < 220) else: @@ -522,6 +543,15 @@ def OnMidiIn(event): return padsToHandle = pdWorkArea + + # if(_PadMode.Mode == MODE_PERFORM): + # print('mixer effect mode', padNum) + # RefreshEffectMapping() + # if(padNum in _ParamPadMapDict.keys()): + # ForceNavSet(nsNone) + # event.handled = HandleEffectPads(padNum) + # return + if(isNoNav()): padsToHandle = pdAllPads @@ -569,7 +599,7 @@ def OnMidiIn(event): HandleShifted(event) if( ctrlID in PadModeCtrls): - event.handled = HandlePadMode(event) + event.handled = HandlePadModeChange(event) elif( ctrlID in TransportCtrls ): event.handled = HandleTransport(event) elif( ctrlID in PageCtrls): # defined as [IDMute1, IDMute2, IDMute3, IDMute4] @@ -713,24 +743,21 @@ def SelectAndShowChannel(newChanIdx): ui.miDisplayRect(mixerTrk, mixerTrk, _rectTime, CR_ScrollToView) def HandlePlaylist(event, padNum): - flIdx = _PadMap[padNum] - - if(padNum in pdPlaylistStripA): - flIdx = _PadMap[padNum].FLIndex - playlist.selectTrack(flIdx) - if(padNum in pdPlaylistMutesA): - flIdx = _PadMap[padNum].FLIndex - playlist.muteTrack(flIdx) - - if(not _isAltMode): - if(padNum in pdPlaylistStripB): - flIdx = _PadMap[padNum].FLIndex + flIdx = _PadMap[padNum].FLIndex + if(flIdx > -1): + print('flidx', flIdx) + + if(padNum in pdPlaylistStripA): playlist.selectTrack(flIdx) - if(padNum in pdPlaylistMutesB): - flIdx = _PadMap[padNum].FLIndex + if(padNum in pdPlaylistMutesA): playlist.muteTrack(flIdx) - - UpdatePlaylistMap(_isAltMode) + + if(not _isAltMode): + if(padNum in pdPlaylistStripB): + playlist.selectTrack(flIdx) + if(padNum in pdPlaylistMutesB): + playlist.muteTrack(flIdx) + UpdatePlaylistMap(_isAltMode) RefreshPlaylist() return True @@ -784,6 +811,19 @@ def HandleProgressBar(padNum): return True +def HandleEffectPads(padNum): + #is an effect mapped? + if(padNum in _ParamPadMapDict.keys()): + slotIdx, slotName, pluginName = GetActiveMixerEffectSlotInfo() + # get Param Value from the pressed pad + offset = _ParamPadMapDict[padNum].Offset + value = _ParamPadMapDict[padNum].GetValueFromPad(padNum) + print('SetMixerPluginParamVal', offset, value, -1, slotIdx) + SetMixerPluginParamVal(offset, value, -1, slotIdx) + RefreshEffectMapping() + return True + + def HandlePads(event, padNum): # 'perfomance' pads will need a pressed AND release... if(_PadMode.Mode == MODE_DRUM): @@ -792,6 +832,7 @@ def HandlePads(event, padNum): elif(_PadMode.Mode == MODE_NOTE): if(padNum in pdWorkArea): return HandleNotes(event, padNum) + # some pads we only need on pressed event @@ -800,6 +841,18 @@ def HandlePads(event, padNum): # macros are handled in OnMidiIn #mode specific + if(False): # todo + if(_PadMode.Mode == MODE_PERFORM): # and (_KnobMode == KM_MIXER): + #is an effect mapped? + if(isKnownMixerEffect()) and (padNum in _ParamPadMapDict.keys()): + slotIdx, slotName, pluginName = GetActiveMixerEffectSlotInfo() + # get Param Value from the pressed pad + offset = _ParamPadMapDict[padNum].Offset + value = _ParamPadMapDict[padNum].GetValueFromPad(padNum) + SetMixerPluginParamVal(offset, value, -1, slotIdx) + RefreshEffectMapping() + return True + if(_PadMode.Mode == MODE_NOTE): if(padNum in pdNav): HandleNav(padNum) @@ -986,7 +1039,8 @@ def HandleNotes(event, padNum): event.data2 = _VelocityMax - if(_ShowChords): +# if(_ShowChords): + if(_ShowChords) and (GetScaleNoteCount(_ScaleIdx) == 7): if (padNum in pdChordBar): chordNum = pdChordBar.index(padNum)+1 noteOn = (event.data2 > 0) @@ -1387,7 +1441,7 @@ def HandlePage(event, ctrlID): elif(_PadMode.Mode == MODE_NOTE) and (ctrlID == IDPage0): - if(_ScaleIdx > 0): + if (GetScaleNoteCount(_ScaleIdx) == 7): #if(_ScaleIdx > 0): _ShowChords = not _ShowChords else: _ShowChords = False @@ -1440,7 +1494,7 @@ def HandleShiftAlt(event, ctrlID): -def HandlePadMode(event): +def HandlePadModeChange(event): global _isAltMode global _isShiftMode global _PadMode @@ -1771,7 +1825,7 @@ def HandleChord(chan, chordNum, noteOn, noteVelocity, play7th, playInverted): global _Chord7th play7th = _Chord7th playInverted = _ChordInvert - realScaleIdx = ScalesList[_ScaleIdx] + realScaleIdx = _ScaleIdx # HarmonicScalesLoaded[_ScaleIdx] # ScalesList[_ScaleIdx] if (GetScaleNoteCount(realScaleIdx) != 7): #if not enough notes to make full chords, do not do anything return @@ -1902,7 +1956,10 @@ def RefreshModes(): RefreshNotes() elif(_PadMode.Mode == MODE_PERFORM): UpdatePlaylistMap(_isAltMode) - RefreshPlaylist() + if(_lastFocus == widPlaylist): + RefreshPlaylist() + if(_lastFocus == widMixer): + RefreshEffectMapping() if(_isAltMode): UpdateMarkerMap() UpdateProgressMap() @@ -2049,6 +2106,10 @@ def RefreshNavPads(): RefreshGridLR() currChan = getCurrChanIdx() + + +# no + if(showUDLRNav): RefreshUDLR() @@ -2056,10 +2117,11 @@ def RefreshNavPads(): if(isNoNav()): return - +# no + for pad in pdNav : SetPadColor(pad, cOff, dimDefault, False) - + if(showChanWinNav) or (showPRNav): RefreshChanWinNav(currChan) @@ -2108,7 +2170,7 @@ def RefreshChanWinNav(currChan = -1): SetPadColor(pdShowChanEditor, color, _ChannelMap[currChan].DimA) if(ui.getFocused(widPianoRoll)): # SetPadColor(pdShowChanPianoRoll, _ChannelMap[currChan].PadBColor, _ChannelMap[currChan].DimB) - SetPadColor(pdShowChanPianoRoll, color, _ChannelMap[currChan].DimA) + SetPadColor(pdShowChanPianoRoll, color, dimBright) else: # SetPadColor(pdShowChanPianoRoll, _ChannelMap[currChan].PadBColor, _ChannelMap[currChan].DimB) SetPadColor(pdShowChanPianoRoll, cWhite, dimBright) @@ -2131,6 +2193,10 @@ def RefreshPageLights(clearOnly = False): if(_PadMode.Mode == MODE_NOTE): if(_ShowChords): SendCC(IDPage0, SingleColorHalfBright) + if (GetScaleNoteCount(_ScaleIdx) == 7): # Can use the chord bar + SendCC(IDTrackSel1, DualColorFull2) + else: + SendCC(IDTrackSel1, DualColorHalfBright1) elif(_PadMode.Mode == MODE_PERFORM): if(_PadMode.IsAlt): SendCC(IDPage0 + _ProgressPadLenIdx, SingleColorHalfBright) @@ -2155,6 +2221,7 @@ def RefreshPageLights(clearOnly = False): if(_ChannelPage > 3): SendCC(IDTrackSel4, SingleColorFull) +_ChromaticOverlay = True def RefreshNotes(): global _PadMap @@ -2180,6 +2247,8 @@ def RefreshNotes(): color = cDimWhite #-1 else: color = cWhite + # elif(_ChromaticOverlay): + else: #non chromatic if(_PadMap[p].NoteInfo.IsRootNote) and (showRoot): if(Settings.ROOT_NOTE_COLOR == cChannel): @@ -2187,16 +2256,14 @@ def RefreshNotes(): else: color = Settings.ROOT_NOTE_COLOR - if(_ShowChords): + if(_ShowChords) and (GetScaleNoteCount(_ScaleIdx) == 7): if(p in pdChordBar): SetPadColor(p, cBlue, dimDefault) elif(p in pdChordFuncs): SetPadColor(p, cOff, dimDefault) else: SetPadColor(p, color, dimDefault) - RefreshChordType() - else: SetPadColor(p, color, dimDefault) @@ -2249,9 +2316,6 @@ def RefreshDrumPads(): # _FPCNotesDict.clear() if( isFPCActive()): # Show Custom FPC Colors - PAD_Semitone = 1 #Retrieve semitone for pad specified by padIndex - PAD_Color = 2 #Retrieve color for pad specified by padIndex - # FPC A Pads #fpcpadIdx = 0 semitone = 0 @@ -2601,7 +2665,9 @@ def RefreshDisplay(): if(_PadMode.Mode == MODE_NOTE): midtext = '' + _ScaleDisplayText - if(_ShowChords): + # if(_ShowChords): + if(_ShowChords) and (GetScaleNoteCount(_ScaleIdx) == 7): + toptext = pm + " - ChB" if(_PadMode.Mode == MODE_DRUM): @@ -2679,76 +2745,76 @@ def RefreshProgressOrig(): #endregion #region Updates / Resets -def UpdatePadMap(): - if(_PadMode.Mode == MODE_PATTERNS): - UpdatePadMapForPatterns() - UpdatePatternModeData() +# def UpdatePadMap(): +# if(_PadMode.Mode == MODE_PATTERNS): +# UpdatePadMapForPatterns() +# UpdatePatternModeData() -def UpdatePadMapForPatterns(): - # should use the _patternMap instead of calls to pattern.XXX finctions - global _PadMap - global _PatternMap - global _PatternSelectedMap - global _PatternCount - - - if(_PadMode.Mode == MODE_PATTERNS): # Pattern mode, set the pattern buttons - - # temp map - patternMap = getPatternMap() - - if(len(_PadMap) == 0): - ResetPadMaps(False) - - # patterns - patternStripA, patternStripB = getPatternPads() - chanStripA, chanStripB = getChannelPads() - pageLen = getPatternModeLength() - patPageOffs = (_PatternPage-1) * pageLen # first page will = 0 - chanPageOffset = (_ChannelPage-1) * pageLen # first page will = 0 - - for padOffset in range(0, pageLen): - - #defaults - padColor = cOff - flIdx = -1 - - pattAPadIdx = patternStripA[padOffset] # the pad to light up - pattBPadIdx = patternStripB[padOffset] # the secondary pad - pattIdx = padOffset + patPageOffs # the pattern in _PatternMap to represent - - chanPadIdxA = chanStripA[padOffset] # the pad to light up - chanPadIdxB = chanStripA[padOffset] # the secondary pad - chanIdx = padOffset + chanPageOffset # the channel to represent at this pad - - if(pattIdx <= len(patternMap)): # when true, there is data to use - flIdx = pattIdx + 1 # fl patterns are 1 based - padColor = patternMap[pattIdx].Color # FLColorToPadColor(patterns.getPatternColor(flIdx)) - #if we have the object, then place it - _PadMap[pattAPadIdx].ItemObject = patternMap[pattIdx] - _PadMap[pattAPadIdx].ItemIndex = pattIdx - _PadMap[pattBPadIdx].ItemObject = patternMap[pattIdx] - _PadMap[pattBPadIdx].ItemIndex = pattIdx - - _PadMap[pattAPadIdx].Color = padColor - _PadMap[pattAPadIdx].FLIndex = flIdx - _PadMap[pattBPadIdx].Color = cDimWhite - _PadMap[pattBPadIdx].FLIndex = flIdx - - # channels - padColor = cOff - flIdx = -1 - if(chanIdx < (_ChannelCount) ): - flIdx = chanIdx # fl channels are 0 based - padColor = FLColorToPadColor(channels.getChannelColor(flIdx)) - - _PadMap[chanPadIdxA].Color = padColor - _PadMap[chanPadIdxA].FLIndex = flIdx - _PadMap[chanPadIdxB].Color = cDimWhite - _PadMap[chanPadIdxB].FLIndex = flIdx - - RefreshPatternStrip() +# def UpdatePadMapForPatterns(): +# # should use the _patternMap instead of calls to pattern.XXX finctions +# global _PadMap +# global _PatternMap +# global _PatternSelectedMap +# global _PatternCount + + +# if(_PadMode.Mode == MODE_PATTERNS): # Pattern mode, set the pattern buttons + +# # temp map +# patternMap = getPatternMap() + +# if(len(_PadMap) == 0): +# ResetPadMaps(False) + +# # patterns +# patternStripA, patternStripB = getPatternPads() +# chanStripA, chanStripB = getChannelPads() +# pageLen = getPatternModeLength() +# patPageOffs = (_PatternPage-1) * pageLen # first page will = 0 +# chanPageOffset = (_ChannelPage-1) * pageLen # first page will = 0 + +# for padOffset in range(0, pageLen): + +# #defaults +# padColor = cOff +# flIdx = -1 + +# pattAPadIdx = patternStripA[padOffset] # the pad to light up +# pattBPadIdx = patternStripB[padOffset] # the secondary pad +# pattIdx = padOffset + patPageOffs # the pattern in _PatternMap to represent + +# chanPadIdxA = chanStripA[padOffset] # the pad to light up +# chanPadIdxB = chanStripA[padOffset] # the secondary pad +# chanIdx = padOffset + chanPageOffset # the channel to represent at this pad + +# if(pattIdx <= len(patternMap)): # when true, there is data to use +# flIdx = pattIdx + 1 # fl patterns are 1 based +# padColor = patternMap[pattIdx].Color # FLColorToPadColor(patterns.getPatternColor(flIdx)) +# #if we have the object, then place it +# _PadMap[pattAPadIdx].ItemObject = patternMap[pattIdx] +# _PadMap[pattAPadIdx].ItemIndex = pattIdx +# _PadMap[pattBPadIdx].ItemObject = patternMap[pattIdx] +# _PadMap[pattBPadIdx].ItemIndex = pattIdx + +# _PadMap[pattAPadIdx].Color = padColor +# _PadMap[pattAPadIdx].FLIndex = flIdx +# _PadMap[pattBPadIdx].Color = cDimWhite +# _PadMap[pattBPadIdx].FLIndex = flIdx + +# # channels +# padColor = cOff +# flIdx = -1 +# if(chanIdx < (_ChannelCount) ): +# flIdx = chanIdx # fl channels are 0 based +# padColor = FLColorToPadColor(channels.getChannelColor(flIdx)) + +# _PadMap[chanPadIdxA].Color = padColor +# _PadMap[chanPadIdxA].FLIndex = flIdx +# _PadMap[chanPadIdxB].Color = cDimWhite +# _PadMap[chanPadIdxB].FLIndex = flIdx + +# RefreshPatternStrip() def UpdatePlaylistMap(selectedOnly = False, mapExtra = True): global _PlaylistMap @@ -2936,6 +3002,7 @@ def UpdateMixerMap(): _MixerMap.clear() for mixNum in range(mixer.trackCount()): # always 127? mix = TnfxMixer(mixNum) + mix.Effects = GetMixerEffects(mixNum) _MixerMap.append(mix) _WalkerName = 'Walker' @@ -3046,24 +3113,30 @@ def GetScaleGrid(newModeIdx=0, rootNote=0, startOctave=2): global _NoteMap global __NoteMapDict + if(len(HarmonicScalesLoaded) == 0): + InitScales() + + if(len(HarmonicScalesLoaded) < (newModeIdx+1)): + return _faveNoteIdx = rootNote _ScaleIdx = newModeIdx - harmonicScale = ScalesList[_ScaleIdx] + print('hs', _ScaleIdx, newModeIdx, HarmonicScalesLoaded[newModeIdx]) + harmonicScaleIdx = _ScaleIdx gridlen = 12 _ScaleNotes.clear() if(_isAltMode) and (_PadMode.Mode == MODE_DRUM): - harmonicScale = ScalesList[0] + harmonicScaleIdx = HarmonicScalesLoaded[0] gridlen = 64 # get lowest octave line lineGrid = [[0] for y in range(gridlen)] # init with 0 - notesInScale = GetScaleNoteCount(harmonicScale) + notesInScale = GetScaleNoteCount(harmonicScaleIdx) #build the lowest notes octave and transpose up from there - BuildNoteGrid(lineGrid, gridlen, 1, rootNote, startOctave, harmonicScale) + BuildNoteGrid(lineGrid, gridlen, 1, rootNote, startOctave, harmonicScaleIdx) # first I make a 5 octave list of notes to refernce later for octave in range(0, 5): @@ -3086,6 +3159,7 @@ def GetScaleGrid(newModeIdx=0, rootNote=0, startOctave=2): padIdx = rowOffset + colOffset MapNoteToPad(padIdx, noteVal) + if(row == 3): # and (GetScaleNoteCount(scale) == 7): #chord row _PadMap[padIdx].NoteInfo.ChordNum = colOffset + 1 else: @@ -3102,7 +3176,7 @@ def GetScaleGrid(newModeIdx=0, rootNote=0, startOctave=2): _PadMap[padIdx].NoteInfo.IsRootNote = (colOffset % notesInScale) == 0 # (colOffset == 0) or (colOffset == notesInScale) - _ScaleDisplayText = NotesList[_faveNoteIdx] + str(startOctave) + " " + HarmonicScaleNamesT[harmonicScale] + _ScaleDisplayText = NotesList[_faveNoteIdx] + str(startOctave) + " " + HarmonicScaleNamesT[harmonicScaleIdx] def PlayMIDINote(chan, note, velocity): if(chan > -1): @@ -3132,6 +3206,9 @@ def SetPadMode(): UpdateMarkerMap() UpdateProgressMap() RefreshProgress() + else: + UpdatePlaylistMap(_isAltMode) + RefreshPlaylist() # elif(_PadMode.Mode == MODE_DRUM): # RefreshNavPads() @@ -3166,7 +3243,13 @@ def getCurrChanPlugin(): return NOSUPPTEXT, None return plugin.getID(), plugin - +# def getCurrMixerPluginNames(slotIdx = 0): +# trkNum = mixer.trackNumber() +# if(plugins.isValid(trkNum, slotIdx)): +# return plugins.getPluginName(trkNum, slotIdx, 0), plugins.getPluginName(trkNum, slotIdx, 1) +# else: +# return 'INVALID', '' + #endregion #region Nav helpers @@ -3276,10 +3359,10 @@ def RefreshGridLR(): def NavScalesList(val): global _ScaleIdx _ScaleIdx += val - if( _ScaleIdx > (len(ScalesList)-1) ): + if( _ScaleIdx > (len(HarmonicScalesLoaded)-1) ): _ScaleIdx = 0 elif( _ScaleIdx < 0 ): - _ScaleIdx = len(ScalesList)-1 + _ScaleIdx = len(HarmonicScalesLoaded)-1 def NavNoteRepeatLength(val): global _NoteRepeatLengthIdx @@ -3307,7 +3390,8 @@ def ShowPianoRoll(showVal, bUpdateDisplay = False, forceChanIdx = -1): ui.openEventEditor(channels.getRecEventId(forceChanIdx) + REC_Chan_PianoRoll, EE_PR) else: ui.hideWindow(widPianoRoll) - + OnRefresh(HW_Dirty_FocusedWindow) + RefreshChannelStrip() if(bUpdateDisplay): @@ -3343,6 +3427,7 @@ def ShowChannelSettings(showVal, bSave, bUpdateDisplay = False): if(bUpdateDisplay): DisplayTimedText('Chan Sett: ' + _showText[showVal]) + OnRefresh(HW_Dirty_FocusedWindow) RefreshChannelStrip() if(bSave): @@ -3372,6 +3457,8 @@ def ShowChannelEditor(showVal, bUpdateDisplay = False): if(bUpdateDisplay): DisplayTextBottom('ChanEdit: ' + _showText[showVal]) + if showVal == 0: + OnRefresh(HW_Dirty_FocusedWindow) RefreshChannelStrip() @@ -3393,33 +3480,23 @@ def ShowPlaylist(showVal, bUpdateDisplay = False): ui.hideWindow(widPlaylist) # _ShowPlaylist = showVal + OnRefresh(HW_Dirty_FocusedWindow) if(bUpdateDisplay): DisplayTimedText('Playlist: ' + _showText[showVal]) -def ShowMixer(showVal, bUpdateDisplay = False): - global _ShowMixer - - isShowing = ui.getVisible(widMixer) - isFocused = ui.getFocused(widMixer) - - #if(showVal == -1): # toggle - #if(_ShowMixer == 1): - if(isShowing == 1) and (isFocused == 1) and (showVal <= 0): - showVal = 0 +def ShowMixer(showVal, bUpdateDisplay = True): + if(ui.getFocused(widMixer) and showVal < 1): + ui.hideWindow(widMixer) else: - showVal = 1 - - if(showVal == 1): ui.showWindow(widMixer) ui.setFocused(widMixer) - else: - ui.hideWindow(widMixer) - - _ShowMixer = showVal if(bUpdateDisplay): - DisplayTimedText('Mixer: ' + _showText[showVal]) + DisplayTimedText('Mixer: ' + _showText[ui.getFocused(widMixer)]) + + OnRefresh(HW_Dirty_FocusedWindow) + def ShowChannelRack(showVal, bUpdateDisplay = False): # global _ShowChanRack @@ -3442,6 +3519,7 @@ def ShowChannelRack(showVal, bUpdateDisplay = False): ui.hideWindow(widChannelRack) # _ShowChanRack = showVal + OnRefresh(HW_Dirty_FocusedWindow) @@ -3505,6 +3583,7 @@ def ShowBrowser(showVal, bUpdateDisplay = False): ForceNavSet(nsUDLR) _prevNavSet = -1 + OnRefresh(HW_Dirty_FocusedWindow) if(bUpdateDisplay): DisplayTimedText('Browser: ' + _showText[showVal]) @@ -3633,9 +3712,23 @@ def ShowNote(note, isOn = True): for pad in pads: SetPadColor(pad, getPadColor(pad), dim) -def UpdateWindowStates(): + +def UpdateAndRefreshWindowStates(): global _PadMode + global _lastFocus + + + time.sleep(.02) # to prevent reading before the window switch is completed, else ui.getFocusedFormID() fails. + + isPluginFocused = ui.getFocusedFormID() in [widPlugin, widPluginEffect, widPluginGenerator] + if(ui.getFocusedFormID() == -1): # manually check + for winID in [widChannelRack, widPlaylist, widMixer]: + if ui.getFocused(winID): + _lastFocus = winID + else: + _lastFocus = ui.getFocusedFormID() + if(Settings.TOGGLE_CR_AND_BROWSER) and (ui.getFocused(widBrowser)): if ui.getVisible(widChannelRack) == 1: ShowChannelRack(0) @@ -3670,6 +3763,8 @@ def UpdateWindowStates(): _ChannelMap[currChan].PadBColor = bColor _ChannelMap[currChan].DimB = dimB + + if isNoMacros(): return @@ -3708,6 +3803,8 @@ def RefreshBrowserButton(): SendCC(IDBrowser, SingleColorOff) # def RefreshWindowStates(): + global _lastFocus + prn(lvlA, 'RefreshWindowStates') RefreshChannelStrip() @@ -3740,6 +3837,7 @@ def RefreshWindowStates(): if(ui.getVisible(widMixer)): shd = shDark if(ui.getFocused(widMixer)): + print('y') shd = shLight SetPadColor(pdMacros[3], getShade(_MacroList[3].PadColor, shd), dimFull) else: @@ -3843,7 +3941,7 @@ def isSampler(chan = -1): def isAudioClip(chan = -1): return (getChannelType(chan) in [CT_AudioClip]) -def getPlugin(pluginName): +def getPlugin(pluginName, slotIdx = -1): ''' Loads the plugin from either (in this order): 1) from _knownPlugins if it exists @@ -3854,6 +3952,18 @@ def getPlugin(pluginName): ''' global LOADED_PLUGINS + + if(slotIdx > -1): # its a mixer effect + baseEffectName, userEffectName = GetMixerSlotPluginName(-1, slotIdx) + if(baseEffectName != 'INVALID'): + if(baseEffectName in KNOWN_PLUGINS.keys()): # is this instance a known plugin? + pl = KNOWN_PLUGINS[baseEffectName].copy() + else: + pl = getPluginInfo(-1, False, False, slotIdx) # unknown, read the info + return pl + return None + + if(pluginName == "GLOBAL CTRL"): # and (isSampler()): return plGlobal @@ -3878,7 +3988,7 @@ def getPlugin(pluginName): if(basePluginName in KNOWN_PLUGINS.keys()): # is this instance a known plugin? pl = KNOWN_PLUGINS[basePluginName].copy() else: - pl = getPluginInfo(-1) # unknown, read the info + pl = getPluginInfo(-1, False, False, slotIdx) # unknown, read the info # rd3d2Present = ('rd3d2 Ext' in pl.ParameterGroups.keys()) # UseExternalKnobPresets = (len(pl.getCurrentKnobParamOffsets()) == 0) and rd3d2Present @@ -4032,7 +4142,6 @@ def getMixer(mixerNum = -1): mixerNum = mixer.trackNumber() return TnfxMixer(mixerNum) - def getEventData(ctrlID): s = '' s2 = '' @@ -4044,14 +4153,78 @@ def getEventData(ctrlID): s2 = device.getLinkedValueString(eventId) DisplayTextAll(s, s2, '') -# def CloseAllWindows(): -# transport.globalTransport(FPT_F12, 1) # close all... -# if(Settings.REOPEN_WINDOWS_AFTER_CLOSE_ALL): -# ShowBrowser(1) -# ShowMixer(1) -# ShowChannelRack(1) -# ShowPlaylist(1) +_ParamPadMapDict = {} +def RefreshEffectMapping(updateOnly = False): + global _PadMap + global _ParamPadMapDict + + _ParamPadMapDict.clear() + slotIdx, slotName, pluginName = GetActiveMixerEffectSlotInfo() + pl = getPlugin(pluginName, slotIdx) + if (pl != None): + + for paramMap in pl.ParamPadMaps: + currVal = GetMixerPluginParamVal(paramMap.Offset, 1, 0) + padList = paramMap.Pads + size = len(paramMap.Pads) - 1 # -1 because FL calcs this way + incby = 1 / size + nv = incby + for idx, pad in enumerate(paramMap.Pads): + dim = dimDim + if(pad > -1): + padVal = idx * incby + _ParamPadMapDict[pad] = paramMap.Offset, padVal + if(currVal == padVal): + dim = dimBright + if(not updateOnly): + SetPadColor(pad, paramMap.Color, dim) + nv += incby + +_lastSlotIdx = -1 +def GetActiveMixerEffectSlotInfo(): + global _lastSlotIdx + slotIdx = -1 + formID = ui.getFocusedFormID() + formCap = ui.getFocusedFormCaption() + slotName = getAlphaNum(formCap.partition(" (")[0].strip(), True) + pluginName = '' + effectKeys = GetMixerSlotEffects().keys() + if(formID > 1000) and (_lastSlotIdx > -1): + effectKeys = [_lastSlotIdx+1] + for slot in effectKeys: + print('slot', slot, effectKeys, formID, _lastSlotIdx) + pname, uname = GetMixerSlotPluginName(-1, slot-1) # 0-based + uname = uname.partition(" (")[0].strip() + if(uname == slotName): + slotIdx = slot-1 # 0 based + pluginName = pname + _lastSlotIdx = slot # remember the 1-based + print('slotIdx={}."{}", plugin="{}"'.format(slotIdx, slotName, pluginName)) + return slotIdx, slotName, pluginName + +def isKnownMixerEffect(): + slotIdx, slotName, pluginName = GetActiveMixerEffectSlotInfo() + return (slotIdx > -1) and (pluginName in KNOWN_PLUGINS.keys()) + +def GetCurrMixerPlugin(): + # gets the names for a specific slot + trkNum = mixer.trackNumber() + slotIdx, slotName, pluginName = GetActiveMixerEffectSlotInfo() + if(pluginName != 'INVALID'): + plugin = getPlugin(pluginName, slotIdx) + if plugin != None: + return plugin.getID(), plugin + return '', None + +def GetEffectsForMixerTrack(trkNum = -1): + # list of TnfxMixerEffect + res = {} + for fx in range(10): # 0-9 + name, uname = GetMixerSlotPluginName(trkNum, fx) + if(name != 'INVALID'): + mxfx = TnfxMixerEffectSlot(fx, name) + res[fx+1] = mxfx + return res - \ No newline at end of file diff --git a/fireNFX_Classes.py b/fireNFX_Classes.py index 833bd31..0052328 100644 --- a/fireNFX_Classes.py +++ b/fireNFX_Classes.py @@ -54,6 +54,7 @@ def __init__(self, name, username = "", type = cpChannelPlugin): self.FLChannelType = -1 self.PresetGroups = {} self.Type = type + self.ParamPadMaps = [] for i in range(4): # pre-allocate these to have 4 each p = TnfxParameter(-1,'',i,'',False) # offset = -1 to identify it's unassigned self.User1Knobs.append(p) @@ -64,11 +65,15 @@ def copy(self): return newPlugin def getID(self): - chanName= channels.getChannelName(channels.selectedChannel()) + chanName = channels.getChannelName(channels.selectedChannel()) + number = channels.selectedChannel() + if(self.Type == cpMixerPlugin): + number = mixer.trackNumber() + chanName = mixer.getTrackName(number) presetName = "NONE" if(plugins.isValid(channels.selectedChannel())): presetName = plugins.getName(channels.selectedChannel(), -1, 6, -1) - return "{}-{}-{}".format(self.PluginName, chanName, presetName) + return "{}-{}-{}-{}".format(self.PluginName, chanName, presetName, number) def getParamNamesForGroup(self, groupName): params = [] @@ -186,18 +191,18 @@ def isTempNavSet(self): return self.NavSet.NavSetID in self.TempNavSets def SetNavSet(self, navSet): - if(navSet not in self.TempNavSets) and (navSet != self.NavSet.NavSetID): + if(self.NavSet.NavSetID in self.AllowedNavSets): self.NavSetHist.append(self.NavSet.NavSetID) # store current NS to recall later if(len(self.NavSetHist) > 10): self.NavSetHist.pop(0) self.NavSet.SetNavSet(navSet) def RecallPrevNavSet(self): - self.NavSet.InitData() prevNS = self.AllowedNavSets[0] # default if(len(self.NavSetHist) > 0): prevNS = self.NavSetHist.pop() - self.NavSet.SetNavSet(prevNS) + self.SetNavSet(prevNS) + class TnfxProgressStep: @@ -220,6 +225,14 @@ def __init__(self, number, name, ticks): def __str__(self): return "Marker #{}, {}, SongPos: {}".format(self.Number, self.Name, self.SongPosAbsTicks) +class TnfxMixerEffectSlot: + def __init__(self, slotIdx, pluginName, color = 0x000000) -> None: + self.SlotIndex = slotIdx + self.PluginName = pluginName + self.Color = color + self.Muted = False + self.MixLevel = 0 + class TnfxMixer: def __init__(self, flIdx): self.FLIndex = flIdx @@ -227,6 +240,7 @@ def __init__(self, flIdx): self.Color = 0x000000 self.Muted = False self.Selected = False + self.Effects = [] self.Update() def __str__(self): return "Mixer #{}.{} ({}) Muted:{}, Selected:{}".format(self.FLIndex, self.Name, self.Color, self.Muted, self.Selected) @@ -395,6 +409,21 @@ def __init__(self): ptMacro = 5 ptNav = 6 ptProgress = 7 +ptParameter = 8 + +class TnfxParamPadMapping: + def __init__(self, offset, color = 0x000000, padList = []): + self.Offset = offset + self.Color = color + self.Pads = padList + def getValueFromPad(self, padIdx): + val = -1 + if(padIdx in self.Pads): + size = len(self.Pads) - 1 # -1 because FL calcs this way + incby = 1 / size + val = self.Pads.index(padIdx) * incby + return val + class TnfxPadMap: def __init__(self, padIndex, flIndex, color, tag): diff --git a/fireNFX_CustomPlugins.py b/fireNFX_CustomPlugins.py index a209bbf..9261f33 100644 --- a/fireNFX_CustomPlugins.py +++ b/fireNFX_CustomPlugins.py @@ -7,4 +7,6 @@ #mixer from pluginFruityLimiter import pluginFruityLimiter +from pluginGrossBeat import pluginGrossBeat + diff --git a/fireNFX_Defs.py b/fireNFX_Defs.py index 5521167..4288636 100644 --- a/fireNFX_Defs.py +++ b/fireNFX_Defs.py @@ -1,7 +1,7 @@ # name = FireNFX Definitions # # much of this is copied from the Image-Line device_Fire code -from harmonicScales import * +from fireNFX_HarmonicScales import * # PAD Modes MODE_PATTERNS = 0 # was MODE_STEP @@ -97,6 +97,11 @@ IDPadFirst = 54 IDPadLast = 117 +PAD_Count = 0 +PAD_Semitone = 1 #Retrieve semitone for pad specified by padIndex +PAD_Color = 2 #Retrieve color for pad specified by padIndex + + TransportCtrls = [IDPatternSong, IDPlay, IDStop, IDRec] ShiftAltCtrls = [IDShift, IDAlt] PadModeCtrls = [IDStepSeq, IDNote, IDDrum, IDPerform] @@ -193,33 +198,34 @@ def getNonPadLightCtrls(): OctavesList = [1,2,3,4,5] -ScalesList = [ - HARMONICSCALE_CHROMATIC, +#build a scales list +# ScalesList = [ +# HARMONICSCALE_CHROMATIC, - # descriptions/key notes from jake @ signals music studio - https://www.youtube.com/channel/UCRDDHLvQb8HjE2r7_ZuNtWA - # Tonality KeyNote Description - HARMONICSCALE_MAJOR, # Major 7th Bright, Happy, Melodic, Joyous - HARMONICSCALE_DORIAN , # Minor 6th Mellow, Smooth, Semi-dark, Spicy - HARMONICSCALE_PHRYGIAN , # Minor 2nd Dark, Tense, Creepy, Exotic - HARMONICSCALE_LYDIAN , # Major 4th Floaty, Quirky, Sci-Fi, Spacy *Jakes fave. - HARMONICSCALE_MIXOLYDIAN , # Major 7th Bright, Upbeat, Rockish, Irish - HARMONICSCALE_AEOLIAN , # Minor 6th Dark, Rock, Sad-ish, - HARMONICSCALE_LOCRIAN , # Diminished ??? ??? (No natural fifth, hard to use) - HARMONICSCALE_MAJORPENTATONIC, # Major - HARMONICSCALE_MINORPENTATONIC, # Minor - HARMONICSCALE_BLUES, - HARMONICSCALE_HARMONICMINOR, - HARMONICSCALE_MELODICMINOR, - HARMONICSCALE_WHOLETONE, - HARMONICSCALE_DIMINISHED, - HARMONICSCALE_MAJORBEBOP, - HARMONICSCALE_DOMINANTBEBOP, - HARMONICSCALE_ENIGMATIC, - HARMONICSCALE_NEAPOLITAN, - HARMONICSCALE_NEAPOLITANMINOR, - HARMONICSCALE_HUNGARIANMINOR, - HARMONICSCALE_ARABIC, - HARMONICSCALE_JAPINSEN] +# # descriptions/key notes from jake @ signals music studio - https://www.youtube.com/channel/UCRDDHLvQb8HjE2r7_ZuNtWA +# # Tonality KeyNote Description +# HARMONICSCALE_MAJOR, # Major 7th Bright, Happy, Melodic, Joyous +# HARMONICSCALE_DORIAN , # Minor 6th Mellow, Smooth, Semi-dark, Spicy +# HARMONICSCALE_PHRYGIAN , # Minor 2nd Dark, Tense, Creepy, Exotic +# HARMONICSCALE_LYDIAN , # Major 4th Floaty, Quirky, Sci-Fi, Spacy *Jakes fave. +# HARMONICSCALE_MIXOLYDIAN , # Major 7th Bright, Upbeat, Rockish, Irish +# HARMONICSCALE_AEOLIAN , # Minor 6th Dark, Rock, Sad-ish, +# HARMONICSCALE_LOCRIAN , # Diminished ??? ??? (No natural fifth, hard to use) +# HARMONICSCALE_MAJORPENTATONIC, # Major +# HARMONICSCALE_MINORPENTATONIC, # Minor +# HARMONICSCALE_BLUES, +# HARMONICSCALE_HARMONICMINOR, +# HARMONICSCALE_MELODICMINOR, +# HARMONICSCALE_WHOLETONE, +# HARMONICSCALE_DIMINISHED, +# HARMONICSCALE_MAJORBEBOP, +# HARMONICSCALE_DOMINANTBEBOP, +# HARMONICSCALE_ENIGMATIC, +# HARMONICSCALE_NEAPOLITAN, +# HARMONICSCALE_NEAPOLITANMINOR, +# HARMONICSCALE_HUNGARIANMINOR, +# HARMONICSCALE_ARABIC, +# HARMONICSCALE_JAPINSEN] lvlN = -2 # Never lvlA = -1 # Always diff --git a/fireNFX_HarmonicScales.py b/fireNFX_HarmonicScales.py new file mode 100644 index 0000000..1e961b1 --- /dev/null +++ b/fireNFX_HarmonicScales.py @@ -0,0 +1,151 @@ +# name=harmonic scales +# url= +# this is a modified and expanded version of harmonicScales.py from the original Fire script. +# + +HARMONICSCALE_LAST = 0 # retain compatibility +HarmonicScaleNamesT = [] # retain compatibility +HarmonicScaleList = [] # retain compatibility + +HarmonicScaleGroups = {} +HarmonicScalesLoaded = [] + +def addScale(scaleName, noteList, groupName = 'UNSORTED'): + global HARMONICSCALE_LAST + global HarmonicScaleNamesT + global HarmonicScaleList + HarmonicScaleList.append(noteList) + HarmonicScalesLoaded.append(noteList) + HarmonicScaleNamesT.append(scaleName) + if(groupName in HarmonicScaleGroups.keys()): + HarmonicScaleGroups[groupName].append(noteList) + else: + HarmonicScaleGroups[groupName] = [noteList] + HARMONICSCALE_LAST = len(HarmonicScaleList)-1 + return HarmonicScaleNamesT[-1], HarmonicScaleList[-1], HARMONICSCALE_LAST + +def GetScaleNoteCount(scale): + Result = 0 + for n in range(0, 13): + if HarmonicScaleList[scale][ n] != -1: + Result += 1 + return Result + +def IsNoteInScale(note, scale): + c = GetScaleNoteCount(scale) + for n in range(0, c + 1): + if (note % 12) == HarmonicScaleList[scale][ n]: + return True + return False + +def IsRootNote(note, scale, offset): + return ((offset - note) % 12) == HarmonicScaleList[scale][ 0] + +def IsBlackKey(note): + return (note % 12) in [1, 3, 6, 8, 10] + +def BuildNoteGrid(grid, sizeX, sizeY, baseNote, baseOctave, scale, rowNoteOffset = 3, bottomToTop = True): + currentNote = 0 + octaveOffset = 0 + nextRowNote = 0 + for j in range(0, sizeY): + for i in range(0, sizeX): + if bottomToTop: + y = sizeY - j - 1 + else: + y = j + grid[i][y] = baseNote + ((baseOctave + octaveOffset) * 12) + HarmonicScaleList[scale][ currentNote] + currentNote += 1 + if HarmonicScaleList[scale][ currentNote] == -1: + currentNote = 0; + octaveOffset += 1 + + octaveOffset = 0; + nextRowNote += rowNoteOffset + currentNote = nextRowNote + if currentNote >= GetScaleNoteCount(scale): + currentNote -= GetScaleNoteCount(scale) + octaveOffset += 1 + +def InitScales(): + # Chromatic ALWAYS needs to be first and always needs to be in the list for fireNFX to function properly. + addScale('Chromatic', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, -1], '') + + # Define the scales chromatic offsets + # you can comment or uncomment to remove or add scales. + # + #addScale('Ionian', [0, 2, 4, 5, 7, 9, 11, -1, -1, -1, -1, -1, -1]) + addScale('Major-ION', [0, 2, 4, 5, 7, 9, 11, -1, -1, -1, -1, -1, -1], 'Faves') + addScale('Maj-Penta', [0, 2, 4, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1], 'Faves') + addScale('Minor-AEO', [0, 2, 3, 5, 7, 8, 10, -1, -1, -1, -1, -1, -1], 'Faves') + addScale('Min-Penta', [0, 3, 5, 7, 10, -1, -1, -1, -1, -1, -1, -1, -1], 'Faves') + # addScale('Min-Harmonic', [0, 2, 3, 5, 7, 8, 11, -1, -1, -1, -1, -1, -1]) + # addScale('Min-Melodic', [0, 2, 3, 5, 7, 9, 11, -1, -1, -1, -1, -1, -1]) + # addScale('Whole Tone', [0, 2, 4, 6, 8, 10, -1, -1, -1, -1, -1, -1, -1]) + # addScale('Diminished', [0, 2, 3, 5, 6, 8, 9, 11, -1, -1, -1, -1, -1]) + # addScale('Japinsen', [0,1, 5, 7, 10, -1, -1, -1, -1, -1, -1, -1, -1]) + # addScale('Major BeBop', [0, 2, 4, 5, 7, 8, 9, 11, -1, -1, -1, -1, -1]) + # addScale('Dominant BeBop', [0,2,4,5,7,9,10,11,-1,-1,-1,-1,-1]) + addScale('Blues', [0, 3, 5, 6, 7, 10, -1, -1, -1, -1, -1, -1, -1]) + # addScale('Arabian', [0, 2, 4, 5, 6, 8, 10, -1, -1, -1, -1, -1, -1]) + # addScale('ArabicOrig', [0, 1, 4, 5, 7, 8, 11, -1, -1, -1, -1, -1, -1]) + # addScale('Enigmatic', [0, 1, 4, 6, 8, 10, 11, -1, -1, -1, -1, -1, -1]) + # addScale('Neopolitan', [0, 1, 3, 5, 7, 8, 11, -1, -1, -1, -1, -1, -1]) + # addScale('NeopolitanOrig', [0, 1, 3, 5, 7, 9, 11, -1, -1, -1, -1, -1, -1]) + # addScale('Neap. Minor', [0, 1, 3, 5, 7, 8, 10, -1, -1, -1, -1, -1, -1]) + # addScale('Neap. Minor Orig', [0, 1, 3, 5, 7, 8, 11, -1, -1, -1, -1, -1, -1]) + addScale('Gypsy', [0, 2, 3, 6, 7, 8, 11, -1, -1, -1, -1, -1, -1], 'Ethnic') + # addScale('DORIAN', [0, 2, 3, 5, 7, 9, 10, -1, -1, -1, -1, -1, -1]) + # addScale('DOR #4', [0, 2, 3, 6, 7, 9, 10, -1, -1, -1, -1, -1, -1]) + # addScale('DOR B2', [0, 1, 3, 5, 6, 8, 9, -1, -1, -1, -1, -1, -1]) + addScale('PHRYGIAN', [0, 1, 3, 5, 7, 8, 10, -1, -1, -1, -1, -1, -1], 'MODES') + addScale('FLAM PHRYGIAN', [0, 1, 3, 4, 5, 7, 8, 10, -1, -1, -1, -1, -1], 'MODES') + # addScale('LYDIAN', [0, 2, 4, 6, 7, 9, 11, -1, -1, -1, -1, -1, -1]) + # addScale('LYD #9', [0, 3, 4, 6, 7, 9, 11, -1, -1, -1, -1, -1, -1]) + # addScale('LYD B7', [0, 2, 4, 6, 7, 9, 10, -1, -1, -1, -1, -1, -1]) + # addScale('MIXO', [0, 2, 4, 5, 7, 9, 10, -1, -1, -1, -1, -1, -1]) + # addScale('MIXO B6', [0, 2, 4, 5, 7, 8, 10, -1, -1, -1, -1, -1, -1]) + # addScale('LOCRIAN', [0, 1, 3, 5, 6, 8, 10, -1, -1, -1, -1, -1, -1]) + # addScale('LOC 2', [0, 2, 3, 5, 6, 8, 10, -1, -1, -1, -1, -1, -1]) + # addScale('LOC 6', [0, 1, 3, 5, 6, 9, 10, -1, -1, -1, -1, -1, -1]) + + # addScale('6-Tone Symmetrical', [0, 1, 4, 5, 8, 9, -1, -1, -1, -1, -1, -1, -1]) + # addScale('8-Tone Spanish', [0, 1, 3, 4, 5, 6, 8, 10, -1, -1, -1, -1, -1]) + # addScale('Altered', [0, 1, 3, 4, 6, 8, 10, -1, -1, -1, -1, -1, -1]) + # addScale('Altered Bb7', [0, 1, 3, 4, 6, 8, 9, -1, -1, -1, -1, -1, -1]) + # addScale('Augm. Ionian', [0, 2, 4, 5, 8, 9, 11, -1, -1, -1, -1, -1, -1]) + # addScale('Augm. Lydian', [0, 2, 4, 6, 8, 9, 11, -1, -1, -1, -1, -1, -1]) + # addScale('Augmented', [0, 3, 4, 7, 8, 11, -1, -1, -1, -1, -1, -1, -1]) + # addScale('Balinese', [0, 1, 3, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1]) + # addScale('Byzantine', [0, 1, 4, 5, 7, 8, 11, -1, -1, -1, -1, -1, -1]) + # addScale('Chinese', [0, 4, 6, 7, 11, -1, -1, -1, -1, -1, -1, -1, -1]) + # addScale('Dim. Half-Wholetone', [0, 1, 3, 4, 6, 7, 9, 10, -1, -1, -1, -1, -1]) + # addScale('Dim. Lydian', [0, 2, 3, 6, 7, 9, 11, -1, -1, -1, -1, -1, -1]) + # addScale('Dim. Whole-Halftone', [0, 2, 3, 5, 6, 8, 9, 11, -1, -1, -1, -1, -1]) + # addScale('Double Harmonic', [0, 1, 4, 5, 7, 8, 11, -1, -1, -1, -1, -1, -1]) + # addScale('Egyptian', [0, 2, 5, 7, 10, -1, -1, -1, -1, -1, -1, -1, -1]) + # addScale('Hindu', [0, 2, 4, 5, 7, 8, 10, -1, -1, -1, -1, -1, -1]) + # addScale('Hirajoshi', [0, 2, 3, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1]) + # addScale('Hungarian Major', [0, 3, 4, 6, 7, 9, 10, -1, -1, -1, -1, -1, -1]) + # addScale('Ichikosucho', [0, 2, 4, 5, 6, 7, 9, 11, -1, -1, -1, -1, -1]) + # addScale('Kumoi', [0, 2, 3, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1]) + # addScale('Leading Whole Tone', [0, 2, 4, 6, 8, 10, 11, -1, -1, -1, -1, -1, -1]) + # addScale('Major Phrygian', [0, 1, 4, 5, 7, 8, 10, -1, -1, -1, -1, -1, -1]) + # addScale('Minor Lydian', [0, 2, 4, 6, 7, 8, 10, -1, -1, -1, -1, -1, -1]) + + # addScale('Mohammedan', [0, 2, 3, 5, 7, 8, 11, -1, -1, -1, -1, -1, -1]) + # addScale('Mongolian', [0, 2, 4, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1]) + # addScale('Natural Minor', [0, 2, 3, 5, 7, 8, 10, -1, -1, -1, -1, -1, -1]) + # addScale('Neap. Major', [0, 1, 3, 5, 7, 9, 11, -1, -1, -1, -1, -1, -1]) + # addScale('Overtone', [0, 2, 4, 6, 7, 9, 10, -1, -1, -1, -1, -1, -1]) + # addScale('Pelog', [0, 1, 3, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1]) + # addScale('Persian', [0, 1, 4, 5, 6, 8, 11, -1, -1, -1, -1, -1, -1]) + # addScale('Prometheus', [0, 2, 4, 6, 9, 10, -1, -1, -1, -1, -1, -1, -1]) + # addScale('Prometheus Neap.', [0, 1, 4, 6, 9, 10, -1, -1, -1, -1, -1, -1, -1]) + # addScale('Purvi Theta', [0, 1, 4, 6, 7, 8, 11, -1, -1, -1, -1, -1, -1]) + # addScale('Todi Theta', [0, 1, 3, 6, 7, 8, 11, -1, -1, -1, -1, -1, -1]) + + +InitScales() +print('{} scales loaded.'.format(len(HarmonicScaleList))) + diff --git a/fireNFX_Helpers.py b/fireNFX_Helpers.py index 512e077..c2574a4 100644 --- a/fireNFX_Helpers.py +++ b/fireNFX_Helpers.py @@ -1,50 +1,113 @@ +# +# Helper for FL Global and PLugin Parameter handling. +# import general import device -from midi import * +import midi import channels import mixer -#from older.OBS_midi import REC_SetChanged +import plugins -def getCurrChanIdx(): # backwards compatibility - return channels.selectedChannel() +# Global def SetNativeParam(offset, value): - return general.processRECEvent(offset, value, REC_SetAll) # REC_SetAll forces the refresh... + return general.processRECEvent(offset, value, midi.REC_SetAll) # REC_SetAll forces the refresh... def GetNativeParam(offset): - return general.processRECEvent(offset, 0, REC_GetValue) + return general.processRECEvent(offset, 0, midi.REC_GetValue) + +# Channel +def getCurrChanIdx(): # backwards compatibility + return channels.selectedChannel() def SetChannelFXParam(offset, value, chanNum = -1): if(chanNum == -1): chanNum = channels.selectedChannel() recEventID = channels.getRecEventId(chanNum) - return general.processRECEvent(recEventID + offset, value, REC_SetAll) # REC_SetAll forces the refresh... + return general.processRECEvent(recEventID + offset, value, midi.REC_SetAll) # REC_SetAll forces the refresh... def GetChannelFXParam(offset, chanNum = -1): if(chanNum == -1): chanNum = channels.selectedChannel() recEventID = channels.getRecEventId(chanNum) - return general.processRECEvent(recEventID + offset, 0, REC_GetValue) + return general.processRECEvent(recEventID + offset, 0, midi.REC_GetValue) + +# MIXER +def SetMixerGenParamVal(offset, value, trkNum = -1): + # usage: SetMixerGenParamVal(midi.REC_Mixer_Vol, 11400, 1) to set the volume of mixer channel # 1 to 11400 + if(trkNum == -1): + trkNum = mixer.trackNumber() + recEventID = mixer.getTrackPluginId(trkNum, 0) + return general.processRECEvent(recEventID + offset, value, midi.REC_SetAll) # REC_SetAll forces the refresh... -def SetMixerParam(offset, value, trkNum = -1): +def GetMixerGenParamVal(offset, trkNum = -1): + # usage: GetMixerGenParamVal(midi.REC_Mixer_Vol, 1) to get the volume of mixer channel #1 + if(trkNum == -1): + trkNum = mixer.trackNumber() + recEventID = mixer.getTrackPluginId(trkNum, 0) + return general.processRECEvent(recEventID + offset, 0, midi.REC_GetValue) + +def SetMixerPluginParamVal(offset, value, trkNum = 0, slotIdx = 0): if(trkNum == -1): trkNum = mixer.trackNumber() - recEventID = channels.getRecEventId(trkNum) - return general.processRECEvent(recEventID + offset, value, REC_SetAll) # REC_SetAll forces the refresh... + res = plugins.setParamValue(value, offset, trkNum, slotIdx) + return res + +def GetMixerPluginParamVal(offset, trkNum = 0, slotIdx = 0): + if(trkNum == -1): + trkNum = mixer.trackNumber() + val = plugins.getParamValue(offset, trkNum, slotIdx) + return val -def GetMixerParam(offset, trkNum = -1): +def GetMixerSlotPluginName(trkNum = -1, slotIdx = 0): if(trkNum == -1): trkNum = mixer.trackNumber() - recEventID = channels.getRecEventId(trkNum) - return general.processRECEvent(recEventID + offset, 0, REC_GetValue) + if(plugins.isValid(trkNum, slotIdx)): + return plugins.getPluginName(trkNum, slotIdx, 0), plugins.getPluginName(trkNum, slotIdx, 1) + else: + return 'INVALID', 'INVALID' -def ScanParams(offsetStart, scanLength = 10, includeZero = True): +def GetMixerSlotEffects(trkNum = -1): + # return a dict of slotNum:'Plguin Name' + res = {} + for fx in range(10): # 0-9 + name, uname = GetMixerSlotPluginName(trkNum, fx) + if(name != 'INVALID'): + res[fx+1] = name + return res + +# Utility +def ScanParams(offsetStart, scanLength = 10, includeBlank = False): + # usage: ScanParams(midi.REC_Mixer_First, 127) for offset in range(scanLength): - offs = offset + offsetStart - val = GetNativeParam(offs) - if val == REC_InvalidID: - val = 'Invalid' - linked = device.getLinkedParamName(offs) - strval = device.getLinkedValueString(offs) - if(includeZero) or (str(val) != '0'): - print('offset {} + {}, value "{}", link {}, strval {}'.format(offsetStart, offset, val, linked, strval)) \ No newline at end of file + try: + offs = offset + offsetStart + val = GetNativeParam(offs) + if val == midi.REC_InvalidID: + val = 'Invalid' + linked = device.getLinkedParamName(offs) + strval = device.getLinkedValueString(offs) + if includeBlank or (len(strval) != 0): # (str(val) != '0'): + print('offset {} + {}, value "{}", link {}, strval "{}"'.format(offsetStart, offset, val, linked, strval)) + except Exception as e: + print('Offset +{}, Scan Exception: {}'.format(offset, e)) + +# classes +class GlobalSettingControl: + def setTempo(self, val): + return SetNativeParam(midi.REC_Tempo, val) + def getTempo(self, ): + return GetNativeParam(midi.REC_Tempo) + def setVolume(self, val): + return SetNativeParam(midi.REC_MainVol, val) + def getVolume(self): + return GetNativeParam(midi.REC_MainVol) + def setPitch(self, val): + return SetNativeParam(midi.REC_MainPitch, val) + def getPitch(self): + return GetNativeParam(midi.REC_MainPitch) + def setSwing(self, val): + return SetNativeParam(midi.REC_MainShuffle, val) + def getSwing(self): + return GetNativeParam(midi.REC_MainShuffle) +flmain = GlobalSettingControl() \ No newline at end of file diff --git a/fireNFX_Utils.py b/fireNFX_Utils.py index 5417ebf..5ee82d3 100644 --- a/fireNFX_Utils.py +++ b/fireNFX_Utils.py @@ -168,13 +168,11 @@ def SetPadRGB(idx, r, g, b): dataOut[i + 1] = r dataOut[i + 2] = g dataOut[i + 3] = b - SendMessageToDevice(MsgIDSetRGBPadLedState, len(dataOut), dataOut) def SendCC(ID, Val): - if (not device.isAssigned()): return device.midiOutNewMsg(MIDI_CONTROLCHANGE + (ID << 8) + (Val << 16), ID) @@ -225,14 +223,20 @@ def getPluginParam(chanIdx, paramIdx, prn = False, mixSlotIdx = -1): # -1 denote valuestr = plugins.getParamValueString(paramIdx, chanIdx, mixSlotIdx) bipolar = False name, uname, varName = getPluginNames(chanIdx, mixSlotIdx) - if(caption != '') and prn: - print(varName + ".addParamToGroup('ALL', TnfxParameter(" + str(paramIdx) +", '" + caption +"', 0, '" + valuestr + "', " + str(bipolar) + ") )") - # print('# Param', paramIdx, caption ) - # print('# Value', paramIdx, value ) - # print('# ValStr', paramIdx, valuestr ) - # print('# Color0', paramIdx, plugins.getColor(chanIdx, -1, 0, paramIdx) ) - # print('# Color1', paramIdx, plugins.getColor(chanIdx, -1, 1, paramIdx) ) - # print('----------------------') + spclCnt = plugins.getPadInfo(chanIdx, mixSlotIdx, PAD_Count, paramIdx) + if(caption != ''): + if prn: + print(varName + ".addParamToGroup('ALL', TnfxParameter(" + str(paramIdx) +", '" + caption +"', 0, '" + valuestr + "', " + str(bipolar) + ") )") + if( spclCnt > 0 ): + semitone = plugins.getPadInfo(chanIdx, mixSlotIdx, PAD_Semitone, paramIdx) + padcolor = plugins.getPadInfo(chanIdx, mixSlotIdx, PAD_Color, paramIdx) + for spclIdx in range(plugins.getPadInfo(chanIdx, mixSlotIdx, 0, paramIdx)): + print('# Semitone: ', semitone ) + print('# Color:', hex(padcolor), padcolor ) + # print('# ValStr', paramIdx, valuestr ) + # print('# Color0', paramIdx, plugins.getColor(chanIdx, -1, 0, paramIdx) ) + # print('# Color1', paramIdx, plugins.getColor(chanIdx, -1, 1, paramIdx) ) + # print('----------------------') return TnfxParameter(paramIdx, caption, value, valuestr, bipolar) @@ -263,10 +267,12 @@ def RemoveBadChars(badChars, textStr): res = res.replace(badChar, '') return res -def getAlphaNum(textStr): +def getAlphaNum(textStr, allowSpaces = False): res = textStr for idx, char in enumerate(textStr): - if(not char.isalnum()): + if (allowSpaces) and (char == ' '): + pass + elif(not char.isalnum()): res = res.replace(char, '') return res diff --git a/pluginGrossBeat.py b/pluginGrossBeat.py new file mode 100644 index 0000000..475e875 --- /dev/null +++ b/pluginGrossBeat.py @@ -0,0 +1,59 @@ +# PluginName: Gross Beat +# Created by: NFX +# +from fireNFX_Classes import TnfxParameter, TnfxChannelPlugin, cpChannelPlugin, cpMixerPlugin, TnfxParamPadMapping +from fireNFX_PluginDefs import USER_PLUGINS +from fireNFX_Colors import * +pluginGrossBeat = TnfxChannelPlugin('Gross Beat', '', cpMixerPlugin) +if(pluginGrossBeat.Name not in USER_PLUGINS.keys()): + USER_PLUGINS[pluginGrossBeat.Name] = pluginGrossBeat + print('Gross Beat parameter definitions loaded.') + +pluginGrossBeat.addParamToGroup('ALL', TnfxParameter(0, 'Time slot', 0, 'Empty', False) ) +pluginGrossBeat.addParamToGroup('ALL', TnfxParameter(1, 'Volume slot', 0, 'Empty', False) ) +pluginGrossBeat.addParamToGroup('ALL', TnfxParameter(2, 'Time mix', 0, '100%', False) ) +pluginGrossBeat.addParamToGroup('ALL', TnfxParameter(3, 'Volume mix', 0, '100%', False) ) +pluginGrossBeat.addParamToGroup('ALL', TnfxParameter(4, 'Volume smoothing attack', 0, '2.00ms', False) ) +pluginGrossBeat.addParamToGroup('ALL', TnfxParameter(5, 'Volume smoothing release', 0, '3.66ms', False) ) +pluginGrossBeat.addParamToGroup('ALL', TnfxParameter(6, 'Volume envelope tension', 0, '0%', False) ) +pluginGrossBeat.addParamToGroup('ALL', TnfxParameter(7, 'Hold delay (bar repeat)', 0, '', False) ) +pluginGrossBeat.addParamToGroup('ALL', TnfxParameter(8, 'Time offset (scratching)', 0, '-000:00:000', False) ) + +pdTimeMap = [ 0, 1, 2, 3, 4, 5, 6, 7, + 16, 17, 18, 19, 20, 21, 22, 23, + 32, 33, 34, 35, 36, 37, 38, 39, + 48, 49, 50, 51, 52, 53, 54, 55, + -1, -1, -1, -1 ] # last four are to pad it to 36 total + +pdVolMap = [ 8, 9, 10, 11, 12, 13, 14, 15, + 24, 25, 26, 27, 28, 29, 30, 31, + 40, 41, 42, 43, 44, 45, 46, 47, + 56, 57, 58, 59, 60, 61, 62, 63, + -1, -1, -1, -1 ] # last four are to pad it to 36 total + +timeMap = TnfxParamPadMapping(0, cGreen, pdTimeMap) +volMap = TnfxParamPadMapping(1, cOrange, pdVolMap) + +pluginGrossBeat.ParamPadMaps.append(timeMap) +pluginGrossBeat.ParamPadMaps.append(volMap) + + +# [PARAMETER OFFSETS] +# Notice, the code lines above contains the text "TnfxParameter(" followed by a number +# That number represents the parameter offset for the parameter described on that line +# You can use the parameter offset number to program your own USER Knob mappings below +# +# [HOW TO SET CUSTOM KNOB MAPPINGS] +# The assignKnobs() function takes a list of up to 8 parameter offsets. +# The list must be in brackets like this [ 21, 12, 3, 7]. Max 8 offsets in list. +# it assigns them in order from : +# USER1, KNOBS 1-4 as the first 4 params +# USER2, KNOBS 1-4 as the second 4 params + +# [ENABLING THE CUSTOM MAPPING] +# Comment/Uncomment the next line to disable/enable the knob mappings. +#pluginGrossBeat.assignKnobs([0, 1, 2, 3, 4, 5, 6, 7]) + +# [LAST STEP. DO NOT FORGET. NEEDED TO INCLUDE YOUR MAPPINGS] +# Add the following line (without the #) to the end of fireNFX_CustomPlugins.py +#from pluginGrossBeat import pluginGrossBeat diff --git a/pluginSTRUMGS2.py b/pluginSTRUMGS2.py index 6233e79..46fe960 100644 --- a/pluginSTRUMGS2.py +++ b/pluginSTRUMGS2.py @@ -5,8 +5,8 @@ plStrumGS2 = TnfxChannelPlugin('Strum GS-2') plStrumGS2.AlwaysRescan = False plStrumGS2.addParamToGroup('GENERAL', TnfxParameter(240, 'Global Volume', 0, '-3.2dB ', False) ) -plStrumGS2.addParamToGroup('GENERAL', TnfxParameter(0, 'Play Mode', 0, 'Guitar ', False, 2) ) -plStrumGS2.addParamToGroup('GENERAL', TnfxParameter(4, 'Strum-Auto', 0, 'Off ', False, 1) ) +plStrumGS2.addParamToGroup('GENERAL', TnfxParameter(0, 'Play Mode', 0, 'Guitar ', False, 3) ) +plStrumGS2.addParamToGroup('GENERAL', TnfxParameter(4, 'Strum-Auto', 0, 'Off ', False, 2) ) plStrumGS2.addParamToGroup('GENERAL', TnfxParameter(5, 'Strum-Speed', 0, '31.8%ˀ ', False) ) plStrumGS2.addParamToGroup('GENERAL', TnfxParameter(6, 'Strum-Velocity', 0, '0.00鐛ˀ ', False) ) plStrumGS2.addParamToGroup('GENERAL', TnfxParameter(7, 'Chord Type', 0, 'Movable ', False) ) @@ -15,7 +15,7 @@ plStrumGS2.addParamToGroup('TEMPO', TnfxParameter(9, 'Loop Tempo', 0, 'Normal ', False) ) plStrumGS2.addParamToGroup('MOD WHEEL', TnfxParameter(2, 'MW-Vib Depth', 0, '51.6%ˀ ', False) ) plStrumGS2.addParamToGroup('MOD WHEEL', TnfxParameter(3, 'MW-Vib Speed', 0, '4.2Hz ', False) ) -plStrumGS2.addParamToGroup('EQ', TnfxParameter(97, 'EQ On', 0, 'On ', False, 1) ) +plStrumGS2.addParamToGroup('EQ', TnfxParameter(97, 'EQ On', 0, 'On ', False, 2) ) plStrumGS2.addParamToGroup('EQ', TnfxParameter(86, 'EQ Lo-Freq', 0, '159Hz ', False) ) plStrumGS2.addParamToGroup('EQ', TnfxParameter(87, 'EQ Lo-Gain', 0, '8.1dBˀ ', False) ) plStrumGS2.addParamToGroup('EQ', TnfxParameter(88, 'EQ Lo-Mid Freq', 0, '241Hz ', False) ) @@ -26,15 +26,15 @@ plStrumGS2.addParamToGroup('EQ', TnfxParameter(93, 'EQ Hi-Mid Q', 0, '0.37鐛ˀ ', False) ) plStrumGS2.addParamToGroup('EQ', TnfxParameter(94, 'EQ Hi-Freq', 0, '2.52kHz ', False) ) plStrumGS2.addParamToGroup('EQ', TnfxParameter(95, 'EQ Hi-Gain', 0, '1.8dBˀ ', False) ) -plStrumGS2.addParamToGroup('EQ', TnfxParameter(96, 'EQ SideChain', 0, 'Normal ', False, 1) ) -plStrumGS2.addParamToGroup('COMPRESSOR', TnfxParameter(104, 'On', 0, 'On ', False, 1) ) +plStrumGS2.addParamToGroup('EQ', TnfxParameter(96, 'EQ SideChain', 0, 'Normal ', False, 2) ) +plStrumGS2.addParamToGroup('COMPRESSOR', TnfxParameter(104, 'On', 0, 'On ', False, 2) ) plStrumGS2.addParamToGroup('COMPRESSOR', TnfxParameter(98, 'Threshold', 0, '-17.4dB ', False) ) plStrumGS2.addParamToGroup('COMPRESSOR', TnfxParameter(99, 'Ratio', 0, '1.50鐛ˀ ', False) ) plStrumGS2.addParamToGroup('COMPRESSOR', TnfxParameter(100, 'Attack', 0, '15.0ms ', False) ) plStrumGS2.addParamToGroup('COMPRESSOR', TnfxParameter(101, 'Release', 0, '150msˀ ', False) ) plStrumGS2.addParamToGroup('COMPRESSOR', TnfxParameter(102, 'Gain', 0, '4.9dBˀ ', False) ) -plStrumGS2.addParamToGroup('COMPRESSOR', TnfxParameter(103, 'Pre', 0, 'Off ', False, 1) ) -plStrumGS2.addParamToGroup('REVERB', TnfxParameter(239, 'Rvb On', 0, 'On ', False, 1) ) +plStrumGS2.addParamToGroup('COMPRESSOR', TnfxParameter(103, 'Pre', 0, 'Off ', False, 2) ) +plStrumGS2.addParamToGroup('REVERB', TnfxParameter(239, 'Rvb On', 0, 'On ', False, 2) ) plStrumGS2.addParamToGroup('REVERB', TnfxParameter(233, 'Rvb Size', 0, 'Studio ', False) ) plStrumGS2.addParamToGroup('REVERB', TnfxParameter(234, 'Rvb Decay', 0, '2.00鐛ˀ ', False) ) plStrumGS2.addParamToGroup('REVERB', TnfxParameter(235, 'Rvb Diffusion', 0, '75.0%ˀ ', False) ) @@ -52,7 +52,7 @@ plStrumGS2.addParamToGroup('PICKUPS', TnfxParameter(249, 'Pickups - Bridge Trim', 0, '0.0dBˀ ', False) ) plStrumGS2.addParamToGroup('PICKUPS', TnfxParameter(250, 'Pickups - Type', 0, 'Single ', False) ) plStrumGS2.addParamToGroup('AMP', TnfxParameter(251, 'Amplifier - Channel', 0, 'Channel ', False) ) -plStrumGS2.addParamToGroup('AMP', TnfxParameter(252, 'Amplifier - Bite', 0, 'Off ', False, 1) ) +plStrumGS2.addParamToGroup('AMP', TnfxParameter(252, 'Amplifier - Bite', 0, 'Off ', False, 2) ) plStrumGS2.addParamToGroup('AMP', TnfxParameter(253, 'Amplifier - Channel 1 Drive', 0, '10.0dB ', False) ) plStrumGS2.addParamToGroup('AMP', TnfxParameter(254, 'Amplifier - Channel 1 Mid', 0, '0.0dBˀ ', False) ) plStrumGS2.addParamToGroup('AMP', TnfxParameter(255, 'Amplifier - Channel 1 Level', 0, '-7.0dB ', False) ) @@ -61,11 +61,11 @@ plStrumGS2.addParamToGroup('AMP', TnfxParameter(258, 'Amplifier - Channel 2 Level', 0, '-17.0dB ', False) ) plStrumGS2.addParamToGroup('AMP', TnfxParameter(259, 'Amplifier - Eq Low', 0, '0.0dBˀ ', False) ) plStrumGS2.addParamToGroup('AMP', TnfxParameter(260, 'Amplifier - Eq High', 0, '0.0dBˀ ', False) ) -plStrumGS2.addParamToGroup('AMP', TnfxParameter(261, 'Amplifier - Amplifier On', 0, 'On ', False, 1) ) +plStrumGS2.addParamToGroup('AMP', TnfxParameter(261, 'Amplifier - Amplifier On', 0, 'On ', False, 2) ) plStrumGS2.addParamToGroup('AMP', TnfxParameter(262, 'Amplifier - Spring Reverb Mix', 0, '20.0%ˀ ', False) ) -plStrumGS2.addParamToGroup('AMP', TnfxParameter(263, 'Amplifier - Spring Reverb On', 0, 'Off ', False, 1) ) +plStrumGS2.addParamToGroup('AMP', TnfxParameter(263, 'Amplifier - Spring Reverb On', 0, 'Off ', False, 2) ) plStrumGS2.addParamToGroup('AMP', TnfxParameter(264, 'Amplifier - Cabinet Open', 0, 'Closed ', False) ) -plStrumGS2.addParamToGroup('AMP', TnfxParameter(265, 'Amplifier - Cabinet On', 0, 'On ', False, 1) ) +plStrumGS2.addParamToGroup('AMP', TnfxParameter(265, 'Amplifier - Cabinet On', 0, 'On ', False, 2) ) plStrumGS2.addParamToGroup('HAMMER ON', TnfxParameter(73, 'HO Amp', 0, '85.0%ˀ ', False) ) plStrumGS2.addParamToGroup('HAMMER ON', TnfxParameter(74, 'HO Tone', 0, '71.7%ˀ ', False) ) plStrumGS2.addParamToGroup('MUTE', TnfxParameter(75, 'Harm Decay', 0, '40.0%ˀ ', False) ) @@ -143,11 +143,11 @@ plStrumGS2.addParamToGroup('STRING-6', TnfxParameter(70, 'S-6 Coupling', 0, '19.8%ˀ ', False) ) plStrumGS2.addParamToGroup('STRING-6', TnfxParameter(71, 'S-6 Balance', 0, '24.9%ˀ ', False) ) plStrumGS2.addParamToGroup('STRING-6', TnfxParameter(72, 'S-6 Volume', 0, '0.0dBˀ ', False) ) -plStrumGS2.addParamToGroup('FX-1', TnfxParameter(105, 'On/Off', 0, 'Off ', False, 1) ) +plStrumGS2.addParamToGroup('FX-1', TnfxParameter(105, 'On/Off', 0, 'Off ', False, 2) ) plStrumGS2.addParamToGroup('FX-1', TnfxParameter(106, 'Effect', 0, 'Distort ', False) ) plStrumGS2.addParamToGroup('FX-1 DELAY', TnfxParameter(107, 'Dly Wet', 0, '-15.5dB ', False) ) plStrumGS2.addParamToGroup('FX-1 DELAY', TnfxParameter(108, 'Dly Dry', 0, '0.0dBˀ ', False) ) -plStrumGS2.addParamToGroup('FX-1 DELAY', TnfxParameter(109, 'Dly Sync On', 0, 'Off ', False, 1) ) +plStrumGS2.addParamToGroup('FX-1 DELAY', TnfxParameter(109, 'Dly Sync On', 0, 'Off ', False, 2) ) plStrumGS2.addParamToGroup('FX-1 DELAY', TnfxParameter(110, 'Dly Sync Rate', 0, '1/16 3 ', False) ) plStrumGS2.addParamToGroup('FX-1 DELAY', TnfxParameter(111, 'Dly Delay', 0, '0.13sˀ ', False) ) plStrumGS2.addParamToGroup('FX-1 DELAY', TnfxParameter(112, 'Dly Feedback', 0, '-15.4dB ', False) ) @@ -162,14 +162,14 @@ plStrumGS2.addParamToGroup('FX-1 PHASER', TnfxParameter(121, 'Phsr Depth', 0, '50.0%ˀ ', False) ) plStrumGS2.addParamToGroup('FX-1 PHASER', TnfxParameter(122, 'Phsr Frequency', 0, '120Hz ', False) ) plStrumGS2.addParamToGroup('FX-1 PHASER', TnfxParameter(123, 'Phsr Feedback', 0, '-8.6dB ', False) ) -plStrumGS2.addParamToGroup('FX-1 PHASER', TnfxParameter(124, 'Phsr Sync On', 0, 'Off ', False, 1) ) +plStrumGS2.addParamToGroup('FX-1 PHASER', TnfxParameter(124, 'Phsr Sync On', 0, 'Off ', False, 2) ) plStrumGS2.addParamToGroup('FX-1 PHASER', TnfxParameter(125, 'Phsr Sync Rate', 0, '1/8 ', False) ) plStrumGS2.addParamToGroup('FX-1 PHASER', TnfxParameter(126, 'Phsr Rate', 0, '1.2Hz ', False) ) plStrumGS2.addParamToGroup('FX-1 VINTAGE CHORUS', TnfxParameter(127, 'Vin-Cho Depth', 0, '44.9%ˀ ', False) ) plStrumGS2.addParamToGroup('FX-1 VINTAGE CHORUS', TnfxParameter(128, 'Vin-Cho Spread', 0, '65.4%ˀ ', False) ) plStrumGS2.addParamToGroup('FX-1 VINTAGE CHORUS', TnfxParameter(129, 'Vin-Cho Delay', 0, '3ms ', False) ) plStrumGS2.addParamToGroup('FX-1 VINTAGE CHORUS', TnfxParameter(130, 'Vin-Cho Feedback', 0, '-35.9dB ', False) ) -plStrumGS2.addParamToGroup('FX-1 VINTAGE CHORUS', TnfxParameter(131, 'Vin-Cho Sync On', 0, 'Off ', False, 1) ) +plStrumGS2.addParamToGroup('FX-1 VINTAGE CHORUS', TnfxParameter(131, 'Vin-Cho Sync On', 0, 'Off ', False, 2) ) plStrumGS2.addParamToGroup('FX-1 VINTAGE CHORUS', TnfxParameter(132, 'Vin-Cho Sync Rate', 0, '1/8 ', False) ) plStrumGS2.addParamToGroup('FX-1 VINTAGE CHORUS', TnfxParameter(133, 'Vin-Cho Rate', 0, '0.9Hz ', False) ) plStrumGS2.addParamToGroup('FX-1 VINTAGE CHORUS', TnfxParameter(134, 'Vin-Cho Mix', 0, '77.2%ˀ ', False) ) @@ -177,19 +177,19 @@ plStrumGS2.addParamToGroup('FX-1 CHORUS', TnfxParameter(136, 'Chorus Depth', 0, '50.0%ˀ ', False) ) plStrumGS2.addParamToGroup('FX-1 CHORUS', TnfxParameter(137, 'Chorus Fat', 0, '2搒 ', False) ) plStrumGS2.addParamToGroup('FX-1 CHORUS', TnfxParameter(138, 'Chorus Spread', 0, '62.0%ˀ ', False) ) -plStrumGS2.addParamToGroup('FX-1 CHORUS', TnfxParameter(139, 'Chorus Sync On', 0, 'Off ', False, 1) ) +plStrumGS2.addParamToGroup('FX-1 CHORUS', TnfxParameter(139, 'Chorus Sync On', 0, 'Off ', False, 2) ) plStrumGS2.addParamToGroup('FX-1 CHORUS', TnfxParameter(140, 'Chorus Sync Rate', 0, '1/4 ', False) ) plStrumGS2.addParamToGroup('FX-1 CHORUS', TnfxParameter(141, 'Chorus Rate', 0, '0.5Hz ', False) ) plStrumGS2.addParamToGroup('FX-1 CHORUS', TnfxParameter(142, 'Chorus Mix', 0, '50.0%ˀ ', False) ) plStrumGS2.addParamToGroup('FX-1 FLANGER', TnfxParameter(143, 'Flanger Depth', 0, '78.0%ˀ ', False) ) plStrumGS2.addParamToGroup('FX-1 FLANGER', TnfxParameter(144, 'Flanger Delay', 0, '30.0ms ', False) ) plStrumGS2.addParamToGroup('FX-1 FLANGER', TnfxParameter(145, 'Flanger Feedback', 0, '-6.0dB ', False) ) -plStrumGS2.addParamToGroup('FX-1 FLANGER', TnfxParameter(146, 'Flanger Sync On', 0, 'Off ', False, 1) ) +plStrumGS2.addParamToGroup('FX-1 FLANGER', TnfxParameter(146, 'Flanger Sync On', 0, 'Off ', False, 2) ) plStrumGS2.addParamToGroup('FX-1 FLANGER', TnfxParameter(147, 'Flanger Sync Rate', 0, '1/4 ', False) ) plStrumGS2.addParamToGroup('FX-1 FLANGER', TnfxParameter(148, 'Flanger Rate', 0, '0.4Hz ', False) ) plStrumGS2.addParamToGroup('FX-1 FLANGER', TnfxParameter(149, 'Flanger Mix', 0, '50.0%ˀ ', False) ) plStrumGS2.addParamToGroup('FX-1 TREMOLO', TnfxParameter(150, 'Trem Depth', 0, '25.0%ˀ ', False) ) -plStrumGS2.addParamToGroup('FX-1 TREMOLO', TnfxParameter(151, 'Trem Sync On', 0, 'Off ', False, 1) ) +plStrumGS2.addParamToGroup('FX-1 TREMOLO', TnfxParameter(151, 'Trem Sync On', 0, 'Off ', False, 2) ) plStrumGS2.addParamToGroup('FX-1 TREMOLO', TnfxParameter(152, 'Trem Sync Rate', 0, '1/32鐛ˀ ', False) ) plStrumGS2.addParamToGroup('FX-1 TREMOLO', TnfxParameter(153, 'Trem Rate', 0, '1.0Hz ', False) ) plStrumGS2.addParamToGroup('FX-1 TREMOLO', TnfxParameter(154, 'Trem Stereo', 0, 'Stereo ', False) ) @@ -199,12 +199,12 @@ plStrumGS2.addParamToGroup('FX-1 AUTO-WAH', TnfxParameter(158, 'Auto-Wah Speed', 0, '69.9%ˀ ', False) ) plStrumGS2.addParamToGroup('FX-1 WAH-WAH', TnfxParameter(159, 'Wah-Wah Depth', 0, '88.8%ˀ ', False) ) plStrumGS2.addParamToGroup('FX-1 WAH-WAH', TnfxParameter(160, 'Wah-Wah Freq', 0, '557Hz ', False) ) -plStrumGS2.addParamToGroup('FX-1 WAH-WAH', TnfxParameter(161, 'Wah-Wah Sync On', 0, 'Off ', False, 1) ) +plStrumGS2.addParamToGroup('FX-1 WAH-WAH', TnfxParameter(161, 'Wah-Wah Sync On', 0, 'Off ', False, 2) ) plStrumGS2.addParamToGroup('FX-1 WAH-WAH', TnfxParameter(162, 'Wah-Wah Sync Rate', 0, '1/8 ', False) ) plStrumGS2.addParamToGroup('FX-1 WAH-WAH', TnfxParameter(163, 'Wah-Wah Rate', 0, '1.7Hz ', False) ) plStrumGS2.addParamToGroup('FX-1 NOTCH FILTER', TnfxParameter(164, 'Notch Depth', 0, '88.8%ˀ ', False) ) plStrumGS2.addParamToGroup('FX-1 NOTCH FILTER', TnfxParameter(165, 'Notch Freq', 0, '557Hz ', False) ) -plStrumGS2.addParamToGroup('FX-1 NOTCH FILTER', TnfxParameter(166, 'Notch Sync On', 0, 'Off ', False, 1) ) +plStrumGS2.addParamToGroup('FX-1 NOTCH FILTER', TnfxParameter(166, 'Notch Sync On', 0, 'Off ', False, 2) ) plStrumGS2.addParamToGroup('FX-1 NOTCH FILTER', TnfxParameter(167, 'Notch Sync Rate', 0, '1/8 ', False) ) plStrumGS2.addParamToGroup('FX-1 NOTCH FILTER', TnfxParameter(168, 'Notch Rate', 0, '1.0Hz ', False) ) plStrumGS2.addParamToGroup('FX-1 EQ', TnfxParameter(267, 'EQ Low Freq', 0, '100Hz ', False) ) @@ -224,11 +224,11 @@ plStrumGS2.addParamToGroup('FX-1 COMPRESSOR', TnfxParameter(281, 'Comp Release', 0, '100msˀ ', False) ) plStrumGS2.addParamToGroup('FX-1 COMPRESSOR', TnfxParameter(282, 'Comp Makeup', 0, '0.0dBˀ ', False) ) plStrumGS2.addParamToGroup('FX-1 COMPRESSOR', TnfxParameter(283, 'Comp Mix', 0, 'W100 D0 ', False) ) -plStrumGS2.addParamToGroup('FX-2', TnfxParameter(169, 'On/Off', 0, 'Off ', False, 1) ) +plStrumGS2.addParamToGroup('FX-2', TnfxParameter(169, 'On/Off', 0, 'Off ', False, 2) ) plStrumGS2.addParamToGroup('FX-2', TnfxParameter(170, 'Effect', 0, 'Tremolo ', False) ) plStrumGS2.addParamToGroup('FX-2 DELAY', TnfxParameter(171, 'Dly Wet', 0, '-15.5dB ', False) ) plStrumGS2.addParamToGroup('FX-2 DELAY', TnfxParameter(172, 'Dly Dry', 0, '0.0dBˀ ', False) ) -plStrumGS2.addParamToGroup('FX-2 DELAY', TnfxParameter(173, 'Dly Sync On', 0, 'Off ', False, 1) ) +plStrumGS2.addParamToGroup('FX-2 DELAY', TnfxParameter(173, 'Dly Sync On', 0, 'Off ', False, 2) ) plStrumGS2.addParamToGroup('FX-2 DELAY', TnfxParameter(174, 'Dly Sync Rate', 0, '1/16 3 ', False) ) plStrumGS2.addParamToGroup('FX-2 DELAY', TnfxParameter(175, 'Dly Delay', 0, '0.14sˀ ', False) ) plStrumGS2.addParamToGroup('FX-2 DELAY', TnfxParameter(176, 'Dly Feedback', 0, '-12.0dB ', False) ) @@ -243,14 +243,14 @@ plStrumGS2.addParamToGroup('FX-2 PHASER', TnfxParameter(185, 'Phsr Depth', 0, '42.0%ˀ ', False) ) plStrumGS2.addParamToGroup('FX-2 PHASER', TnfxParameter(186, 'Phsr Frequency', 0, '233Hz ', False) ) plStrumGS2.addParamToGroup('FX-2 PHASER', TnfxParameter(187, 'Phsr Feedback', 0, '-6.6dB ', False) ) -plStrumGS2.addParamToGroup('FX-2 PHASER', TnfxParameter(188, 'Phsr Sync On', 0, 'Off ', False, 1) ) +plStrumGS2.addParamToGroup('FX-2 PHASER', TnfxParameter(188, 'Phsr Sync On', 0, 'Off ', False, 2) ) plStrumGS2.addParamToGroup('FX-2 PHASER', TnfxParameter(189, 'Phsr Sync Rate', 0, '1/4 ', False) ) plStrumGS2.addParamToGroup('FX-2 PHASER', TnfxParameter(190, 'Phsr Rate', 0, '0.4Hz ', False) ) plStrumGS2.addParamToGroup('FX-2 VINTAGE CHORUS', TnfxParameter(191, 'Vin-Cho Depth', 0, '25.9%ˀ ', False) ) plStrumGS2.addParamToGroup('FX-2 VINTAGE CHORUS', TnfxParameter(192, 'Vin-Cho Spread', 0, '0.0%鐛ˀ ', False) ) plStrumGS2.addParamToGroup('FX-2 VINTAGE CHORUS', TnfxParameter(193, 'Vin-Cho Delay', 0, '40ms鐛ˀ ', False) ) plStrumGS2.addParamToGroup('FX-2 VINTAGE CHORUS', TnfxParameter(194, 'Vin-Cho Feedback', 0, '-40.0dB ', False) ) -plStrumGS2.addParamToGroup('FX-2 VINTAGE CHORUS', TnfxParameter(195, 'Vin-Cho Sync On', 0, 'Off ', False, 1) ) +plStrumGS2.addParamToGroup('FX-2 VINTAGE CHORUS', TnfxParameter(195, 'Vin-Cho Sync On', 0, 'Off ', False, 2) ) plStrumGS2.addParamToGroup('FX-2 VINTAGE CHORUS', TnfxParameter(196, 'Vin-Cho Sync Rate', 0, '1/4 ', False) ) plStrumGS2.addParamToGroup('FX-2 VINTAGE CHORUS', TnfxParameter(197, 'Vin-Cho Rate', 0, '1.0Hz ', False) ) plStrumGS2.addParamToGroup('FX-2 VINTAGE CHORUS', TnfxParameter(198, 'Vin-Cho Mix', 0, '17.0%ˀ ', False) ) @@ -258,19 +258,19 @@ plStrumGS2.addParamToGroup('FX-2 CHORUS', TnfxParameter(200, 'Chorus Depth', 0, '50.0%ˀ ', False) ) plStrumGS2.addParamToGroup('FX-2 CHORUS', TnfxParameter(201, 'Chorus Fat', 0, '4搒 ', False) ) plStrumGS2.addParamToGroup('FX-2 CHORUS', TnfxParameter(202, 'Chorus Spread', 0, '62.0%ˀ ', False) ) -plStrumGS2.addParamToGroup('FX-2 CHORUS', TnfxParameter(203, 'Chorus Sync On', 0, 'Off ', False, 1) ) +plStrumGS2.addParamToGroup('FX-2 CHORUS', TnfxParameter(203, 'Chorus Sync On', 0, 'Off ', False, 2) ) plStrumGS2.addParamToGroup('FX-2 CHORUS', TnfxParameter(204, 'Chorus Sync Rate', 0, '1/4 ', False) ) plStrumGS2.addParamToGroup('FX-2 CHORUS', TnfxParameter(205, 'Chorus Rate', 0, '0.5Hz ', False) ) plStrumGS2.addParamToGroup('FX-2 CHORUS', TnfxParameter(206, 'Chorus Mix', 0, '20.0%ˀ ', False) ) plStrumGS2.addParamToGroup('FX-2 FLANGER', TnfxParameter(207, 'Flanger Depth', 0, '78.0%ˀ ', False) ) plStrumGS2.addParamToGroup('FX-2 FLANGER', TnfxParameter(208, 'Flanger Delay', 0, '30.0ms ', False) ) plStrumGS2.addParamToGroup('FX-2 FLANGER', TnfxParameter(209, 'Flanger Feedback', 0, '-6.0dB ', False) ) -plStrumGS2.addParamToGroup('FX-2 FLANGER', TnfxParameter(210, 'Flanger Sync On', 0, 'Off ', False, 1) ) +plStrumGS2.addParamToGroup('FX-2 FLANGER', TnfxParameter(210, 'Flanger Sync On', 0, 'Off ', False, 2) ) plStrumGS2.addParamToGroup('FX-2 FLANGER', TnfxParameter(211, 'Flanger Sync Rate', 0, '1/4 ', False) ) plStrumGS2.addParamToGroup('FX-2 FLANGER', TnfxParameter(212, 'Flanger Rate', 0, '0.4Hz ', False) ) plStrumGS2.addParamToGroup('FX-2 FLANGER', TnfxParameter(213, 'Flanger Mix', 0, '50.0%ˀ ', False) ) plStrumGS2.addParamToGroup('FX-2 TREMOLO', TnfxParameter(214, 'Trem Depth', 0, '50.0%ˀ ', False) ) -plStrumGS2.addParamToGroup('FX-2 TREMOLO', TnfxParameter(215, 'Trem Sync On', 0, 'Off ', False, 1) ) +plStrumGS2.addParamToGroup('FX-2 TREMOLO', TnfxParameter(215, 'Trem Sync On', 0, 'Off ', False, 2) ) plStrumGS2.addParamToGroup('FX-2 TREMOLO', TnfxParameter(216, 'Trem Sync Rate', 0, '1/4 ', False) ) plStrumGS2.addParamToGroup('FX-2 TREMOLO', TnfxParameter(217, 'Trem Rate', 0, '3.0Hz ', False) ) plStrumGS2.addParamToGroup('FX-2 TREMOLO', TnfxParameter(218, 'Trem Stereo', 0, 'Mono鐛ˀ ', False) ) @@ -280,12 +280,12 @@ plStrumGS2.addParamToGroup('FX-2 AUTO-WAH', TnfxParameter(222, 'Auto-Wah Speed', 0, '71.0%ˀ ', False) ) plStrumGS2.addParamToGroup('FX-2 WAH-WAH', TnfxParameter(223, 'Wah-Wah Depth', 0, '53.9%ˀ ', False) ) plStrumGS2.addParamToGroup('FX-2 WAH-WAH', TnfxParameter(224, 'Wah-Wah Freq', 0, '707Hz ', False) ) -plStrumGS2.addParamToGroup('FX-2 WAH-WAH', TnfxParameter(225, 'Wah-Wah Sync On', 0, 'Off ', False, 1) ) +plStrumGS2.addParamToGroup('FX-2 WAH-WAH', TnfxParameter(225, 'Wah-Wah Sync On', 0, 'Off ', False, 2) ) plStrumGS2.addParamToGroup('FX-2 WAH-WAH', TnfxParameter(226, 'Wah-Wah Sync Rate', 0, '1/4 ', False) ) plStrumGS2.addParamToGroup('FX-2 WAH-WAH', TnfxParameter(227, 'Wah-Wah Rate', 0, '1.7Hz ', False) ) plStrumGS2.addParamToGroup('FX-2 NOTCH FILTER', TnfxParameter(228, 'Notch Depth', 0, '50.0%ˀ ', False) ) plStrumGS2.addParamToGroup('FX-2 NOTCH FILTER', TnfxParameter(229, 'Notch Freq', 0, '620Hz ', False) ) -plStrumGS2.addParamToGroup('FX-2 NOTCH FILTER', TnfxParameter(230, 'Notch Sync On', 0, 'Off ', False, 11) ) +plStrumGS2.addParamToGroup('FX-2 NOTCH FILTER', TnfxParameter(230, 'Notch Sync On', 0, 'Off ', False, 12) ) plStrumGS2.addParamToGroup('FX-2 NOTCH FILTER', TnfxParameter(231, 'Notch Sync Rate', 0, '1/4 ', False) ) plStrumGS2.addParamToGroup('FX-2 NOTCH FILTER', TnfxParameter(232, 'Notch Rate', 0, '1.5Hz ', False) ) plStrumGS2.addParamToGroup('FX-2 EQ', TnfxParameter(284, 'EQ Lo Freq', 0, '100Hz ', False) ) @@ -451,9 +451,8 @@ plStrumGS2.addParamToGroup('MIDI CCs', TnfxParameter(4239, 'MIDI CCs Channel 16 Aftertouch', 0, '', False) ) # set up the predetermined USER1 and/or USER2 knob parameters to link to the 8 macros -#plStrumGS2.assignParameterToUserKnob(KM_USER1, 0, TnfxParameter(0, 'Play Mode', 0, 'Guitar', False, 2) ) plStrumGS2.assignParameterToUserKnob(KM_USER1, 0, plStrumGS2.getParamFromOffset(0) ) -plStrumGS2.assignParameterToUserKnob(KM_USER1, 1, TnfxParameter(4, 'Auto Strum', 0, 'Off', False, 1) ) +plStrumGS2.assignParameterToUserKnob(KM_USER1, 1, TnfxParameter(4, 'Auto Strum', 0, 'Off', False, 2) ) plStrumGS2.assignParameterToUserKnob(KM_USER1, 2, TnfxParameter(7, 'Chord Type', 0, 'Movable', False) ) plStrumGS2.assignParameterToUserKnob(KM_USER1, 3, TnfxParameter(8, 'Voicing Pos', 0, 'Fret 1', False) ) # -----------------------------------------------------------------