so here is the MidiHandler Class I came up with-- it is pretty rudimentary
##feel free to use or modify-- Daniel Potthast ##www.danielraphael.info
import pygame
import pygame.midi
pgm=pygame.midi
pgm.init()
midin=pgm.Input(1) #this value will vary with your hardware mine is 1
class MidiHandler():
def __init__(self):
global midin
self.midin=midin
def mRead(self):
self.mOut=self.midin.read(1)
if self.mOut:
return self.mOut
else:return None
def mRtrn(self,mRaw,sldr,chan=176):
if mRaw:
mChan = mRaw[0][0][0]
mSld = mRaw[0][0][1]
mVal = mRaw[0][0][2]
if mChan==chan and mSld==sldr:
return mVal
else:return None
def mKill(self):
midin.close()
def mRange(self,mInput, min=-1, max=1): #restricts output range
mRatio = (max-min)/127.0
mOut = ((mInput-1)*mRatio)+min
return mOut
def mTime(self):
return self.pgm.time()
here is the implementation in the main module:
from MidiHandler import *
x=MidiHandler()
#this line in the main __init__
base.accept('1',self.midiEnable)
def midiEnable(self):
def setOut(): #establish variables and initial values
self.mOut1=1
self.mOut2=1
self.mOut3=1
self.mOut4=0
self.mOut5=0
self.mOut6=0
self.mOut7=1
self.mOut8=1
self.mOut9=1
self.mOut10=1
#and so on for all knobs and sliders
setOut()
def mTask(task):
self.mIn=x.mRead()
self.step=task.time
def setCtrl(): #returns to each variable if value is not None
self.mCtrl1=x.mRtrn(self.mIn,1)
self.mCtrl2=x.mRtrn(self.mIn,2)
self.mCtrl3=x.mRtrn(self.mIn,3)
self.mCtrl4=x.mRtrn(self.mIn,4)
self.mCtrl5=x.mRtrn(self.mIn,5)
self.mCtrl6=x.mRtrn(self.mIn,6)
self.mCtrl7=x.mRtrn(self.mIn,7)
self.mCtrl8=x.mRtrn(self.mIn,8)
self.mCtrl9=x.mRtrn(self.mIn,9)
self.mCtrl10=x.mRtrn(self.mIn,10)
#and so on for all your knobs and sliders
setCtrl()
def setRead():
if self.mCtrl1:
self.mRg=x.mRange(self.mCtrl1,-90,90)
self.mOut1=self.mRg
elif self.mCtrl2:
self.mRg=x.mRange(self.mCtrl2,-90,90)
self.mOut2=self.mRg
elif self.mCtrl3:
self.mRg=x.mRange(self.mCtrl3,-90,90)
self.mOut3=self.mRg
elif self.mCtrl4:
self.mRg=x.mRange(self.mCtrl4,-10,10)
self.mOut4=self.mRg
elif self.mCtrl5:
self.mRg=x.mRange(self.mCtrl5,-10,10)
self.mOut5=self.mRg
elif self.mCtrl6:
self.mRg=x.mRange(self.mCtrl6,-10,10)
self.mOut6=self.mRg
elif self.mCtrl7:
self.mRg=x.mRange(self.mCtrl7,-180,180)
self.mOut7=self.mRg
elif self.mCtrl8:
self.mRg=x.mRange(self.mCtrl8,-180,180)
self.mOut8=self.mRg
elif self.mCtrl9:
self.mRg=x.mRange(self.mCtrl9,-180,180)
self.mOut9=self.mRg
elif self.mCtrl10:
self.mRg=x.mRange(self.mCtrl10,-30.0,30.0)
self.mOut10=self.mRg
#and so on for your knobs, sliders, etc...
#place commands for midi to influence here:
#see example below
return task.cont
base.taskMgr.add(mTask, "mTask")
I realize this is probably far more verbose than it needs to be (and it is even abridged)
however it does work… I think a ‘for loop’ may be able to do the initializing of the variables more efficiently… but I would not be able to assign individual default values that way.
the “x.mRange” calls a simple function to make the 1-128 midi return values stick to whatever range of values I require
so:
elif self.mCtrl28:
self.mRg=x.mRange(self.mCtrl28,-31.4,31.4)
self.mOut28=self.mRg
This makes the 28th midi slider output values from -31.4 to 31.4 rather than 1-128
after the midi is read I can then assign the output to whatever I need to e.g.
self.actor2Pivot.setHpr(self.mOut1,self.mOut2,self.mOut3)
#allows x,y,z rotation to be handled by sliders 1,2,3
these are placed at the bottom of the same task.
I have not used the x.mKill function but include it in the module if needed…
I should experiment more, but I am not sure if this could be done with two or more tasks however, the midi seems to get along much better if it is all handled with one task…
**what I have noticed with this implementation is that the midi read values buffer up and the midi clock is running 10-20 clicks per task frame so if you go crazy with your sliders it will take a little time for the individual reads to catch up to all the values stacked up in the buffer.
Please Please Please if any of you have a better way of doing this I am all ears, however it was gratifying and educational to actually get this far-- I hope this comes in handy to someone out there.
dp