diff --git a/src/caitlib_helpers.py b/src/caitlib_helpers.py index 64db1c5..3bb37ce 100644 --- a/src/caitlib_helpers.py +++ b/src/caitlib_helpers.py @@ -17,3 +17,280 @@ # For a full copy of the GNU General Public License see the COPYING file import caitlib + +# ------------------------------------------------------------------------------ +# Instances + +# Caitlib instance +class CailibInstance(object): + def __init__(self, instanceName): + object.__init__(self) + + try: + self.m_lib = caitlib.init(instanceName) + except: + self.m_lib = None + + def isOk(self): + return bool(self.m_lib) + + def close(self): + caitlib.close(self.m_lib) + self.m_lib = None + + # --------------------------------- + + def createPort(self, portName): + return CailibPort(self.m_lib, portName) + + # --------------------------------- + + def wantEvents(self, yesNo): + caitlib.want_events(self.m_lib, yesNo) + + def getEvent(self): + return caitlib.get_event(self.m_lib) + +# Caitlib port +class CailibPort(object): + def __init__(self, instance, portName): + object.__init__(self) + + self.m_lib = instance + self.m_port = caitlib.create_port(self.m_lib, portName) + + def isOk(self): + return bool(self.m_port >= 0) + + def destroy(self): + caitlib.destroy_port(self.m_lib, self.m_port) + self.m_port = -1 + + # --------------------------------- + + def addControl(self, time, channel, controller, value): + return ControlEvent(self, time, channel, controller, value) + + def addNote(self, time, channel, pitch, velocity, duration): + return NoteEvent(self, time, channel, pitch, velocity, duration) + + def addChannelPressure(self, time, channel, value): + return ChannelPressureEvent(self, time, channel, value) + + def addProgram(self, time, channel, bank, program): + return ProgramEvent(self, time, channel, bank, program) + + def addPitchWheel(self, time, channel, value): + return PitchWheelEvent(self, time, channel, value) + +# ------------------------------------------------------------------------------ +# Events + +# Abstract event +class AbstractEvent(object): + def __init__(self, port, time, channel): + object.__init__(self) + + if 0 < channel > 15: + print("AbstractEvent(%i, %i) - invalid channel", time, channel) + channel = 0 + + if time < 0: + print("AbstractEvent(%i, %i) - invalid time", time, channel) + time = 0 + + # Channel, 0 - 15 + self.m_channel = channel + + # Time in which the event starts, in ticks + self.m_time = time + + # Store port instance for later + self.m_port = port + + def channel(self): + return self.m_channel + + def time(self): + return self.m_time + + def getRawMidiData(self): + return () + +# Control event +class ControlEvent(AbstractEvent): + def __init__(self, port, time, channel, controller, value): + AbstractEvent.__init__(self, port, time, channel) + + if 1 < controller > 127: + print("ControlEvent(%i, %i) - invalid controller", controller, value) + controller = 0 + + if 0 < value > 127: + print("ControlEvent(%i, %i) - invalid value", controller, value) + value = 0 + + # Controller + self.m_controller = controller + + # Value + self.m_value = value + + # Put event in caitlib + caitlib.put_control(self.m_port.m_lib, self.m_port.m_port, self.m_time, self.m_channel, self.m_controller, self.m_value) + + def controller(self): + return self.m_controller + + def value(self): + return self.m_value + + def getRawMidiData(self): + event = { self.m_time: + (caitlib.MIDI_EVENT_TYPE_CONTROL + self.m_channel, self.m_controller, self.m_value) + } + return (event,) + +# Note event +class NoteEvent(AbstractEvent): + def __init__(self, port, time, channel, pitch, velocity, duration): + AbstractEvent.__init__(self, port, time, channel) + + if duration < 1: + print("NoteEvent(%i, %i, %i) - invalid duration", pitch, velocity, duration) + duration = 1 + + if 0 < pitch > 127: + print("NoteEvent(%i, %i, %i) - invalid pitch", pitch, velocity, duration) + pitch = 0 + + if 0 < velocity > 127: + print("NoteEvent(%i, %i, %i) - invalid velocity", pitch, velocity, duration) + velocity = 0 + + # Duration of note, in ticks + self.m_duration = duration + + # Pitch + self.m_pitch = pitch + + # Velocity + self.m_velocity = velocity + + # Put event in caitlib + caitlib.put_note_on(self.m_port.m_lib, self.m_port.m_port, self.m_time, self.m_channel, self.m_pitch, self.m_velocity) + caitlib.put_note_off(self.m_port.m_lib, self.m_port.m_port, self.m_time+self.m_duration, self.m_channel, self.m_pitch, self.m_velocity) + + def duration(self): + return self.m_duration + + def pitch(self): + return self.m_pitch + + def velocity(self): + return self.m_velocity + + def getRawMidiData(self): + noteOn = { self.m_time: + (caitlib.MIDI_EVENT_TYPE_NOTE_ON + self.m_channel, self.m_pitch, self.m_velocity) + } + noteOff = { self.m_time+self.m_duration: + (caitlib.MIDI_EVENT_TYPE_NOTE_OFF + self.m_channel, self.m_pitch, self.m_velocity) + } + return (noteOn, noteOff) + +# Channel pressure event +class ChannelPressureEvent(AbstractEvent): + def __init__(self, port, time, channel, value): + AbstractEvent.__init__(self, port, time, channel) + + if 0 < value > 127: + print("ChannelPressureEvent(%i) - invalid value", value) + value = 100 + + # Value + self.m_value = value + + # Put event in caitlib + caitlib.put_channel_pressure(self.m_port.m_lib, self.m_port.m_port, self.m_time, self.m_channel, self.m_value) + + def value(self): + return self.m_value + + def getRawMidiData(self): + event = { self.m_time: + (caitlib.MIDI_EVENT_TYPE_CHANNEL_PRESSURE + self.m_channel, self.m_value) + } + return (event,) + +# Program event +class ProgramEvent(AbstractEvent): + def __init__(self, port, time, channel, bank, program): + AbstractEvent.__init__(self, port, time, channel) + + if 0 < bank > 127: + print("ProgramEvent(%i, %i) - invalid bank", bank, program) + bank = 0 + + if 0 < program > 127: + print("ProgramEvent(%i, %i) - invalid program", bank, program) + program = 0 + + # Bank + self.m_bank = bank + + # Program + self.m_program = program + + # Put event in caitlib + caitlib.put_control(self.m_port.m_lib, self.m_port.m_port, self.m_time, self.m_channel, 0, self.m_bank) + caitlib.put_program(self.m_port.m_lib, self.m_port.m_port, self.m_time, self.m_channel, self.m_program) + + def bank(self): + return self.m_bank + + def program(self): + return self.m_program + + def getRawMidiData(self): + bank = { self.m_time: + (caitlib.MIDI_EVENT_TYPE_CONTROL + self.m_channel, 0x00, self.m_bank) + } + program = { self.m_time: + (caitlib.MIDI_EVENT_TYPE_PROGRAM + self.m_channel, self.m_program) + } + return (bank, program) + +# PitchWheel event +class PitchWheelEvent(AbstractEvent): + def __init__(self, port, time, channel, value): + AbstractEvent.__init__(self, port, time, channel) + + if -8192 < value > 8192: + print("PitchWheelEvent(%i) - invalid value", value) + value = 0 + + # Value + self.m_value = value + + # Put event in caitlib + caitlib.put_pitchwheel(self.m_port.m_lib, self.m_port.m_port, self.m_time, self.m_channel, self.m_value) + + def value(self): + return self.m_value + + def getRawMidiData(self): + value = self.m_value + 8192; + lsb = value & 0x7F + msb = value >> 7 + event = { self.m_time: + (caitlib.MIDI_EVENT_TYPE_PITCH_WHEEL + self.m_channel, lsb, msb) + } + return (event,) + +# ------------------------------------------------------------------------------ +# Data Sets + +class Part(object): + def __init__(self): + object.__init__(self) diff --git a/src/caitlyn.py b/src/caitlyn.py index 0e05cf1..ab534c7 100755 --- a/src/caitlyn.py +++ b/src/caitlyn.py @@ -99,125 +99,100 @@ class CaitlynMainW(QMainWindow, ui_caitlyn.Ui_CaitlynMainW): self.item1 = CaitlynCanvasBox(self.scene) # Sequencer test code - self.m_seq = caitlib.init("Caitlyn") - self.m_port1 = caitlib.create_port(self.m_seq, "out1") - - m = 44 - - caitlib.put_control(self.m_seq, self.m_port1, 0*m, 0, 7, 99) - caitlib.put_control(self.m_seq, self.m_port1, 0*m, 0, 10, 63) - caitlib.put_control(self.m_seq, self.m_port1, 0*m, 0, 0, 0) - - # 0 PrCh ch=1 p=0 -- TODO jack_midi_put_program() - - # 0 On ch=1 n=64 v=90 - # 325 Off ch=1 n=64 v=90 - # 384 On ch=1 n=62 v=90 - # 709 Off ch=1 n=62 v=90 - # 768 On ch=1 n=60 v=90 - # 1093 Off ch=1 n=60 v=90 - caitlib.put_note_on(self.m_seq, self.m_port1, 0*m, 0, 64, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 325*m, 0, 64, 90) - caitlib.put_note_on(self.m_seq, self.m_port1, 384*m, 0, 62, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 709*m, 0, 62, 90) - caitlib.put_note_on(self.m_seq, self.m_port1, 768*m, 0, 60, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 1093*m, 0, 60, 90) - - # 1152 On ch=1 n=62 v=90 - # 1477 Off ch=1 n=62 v=90 - # 1536 On ch=1 n=64 v=90 - # 1861 Off ch=1 n=64 v=90 - # 1920 On ch=1 n=64 v=90 - # 2245 Off ch=1 n=64 v=90 - caitlib.put_note_on(self.m_seq, self.m_port1, 1152*m, 0, 62, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 1477*m, 0, 62, 90) - caitlib.put_note_on(self.m_seq, self.m_port1, 1536*m, 0, 64, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 1861*m, 0, 64, 90) - caitlib.put_note_on(self.m_seq, self.m_port1, 1920*m, 0, 64, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 2245*m, 0, 64, 90) - - # 2304 On ch=1 n=64 v=90 - # 2955 Off ch=1 n=64 v=90 - # 3072 On ch=1 n=62 v=90 - # 3397 Off ch=1 n=62 v=90 - # 3456 On ch=1 n=62 v=90 - # 3781 Off ch=1 n=62 v=90 - caitlib.put_note_on(self.m_seq, self.m_port1, 2304*m, 0, 64, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 2955*m, 0, 64, 90) - caitlib.put_note_on(self.m_seq, self.m_port1, 3072*m, 0, 62, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 3397*m, 0, 62, 90) - caitlib.put_note_on(self.m_seq, self.m_port1, 3456*m, 0, 62, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 3781*m, 0, 62, 90) - - # 3840 On ch=1 n=62 v=90 - # 4491 Off ch=1 n=62 v=90 - # 4608 On ch=1 n=64 v=90 - # 4933 Off ch=1 n=64 v=90 - # 4992 On ch=1 n=67 v=90 - # 5317 Off ch=1 n=67 v=90 - caitlib.put_note_on(self.m_seq, self.m_port1, 3840*m, 0, 62, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 4491*m, 0, 62, 90) - caitlib.put_note_on(self.m_seq, self.m_port1, 4608*m, 0, 64, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 4933*m, 0, 64, 90) - caitlib.put_note_on(self.m_seq, self.m_port1, 4992*m, 0, 67, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 5317*m, 0, 67, 90) - - # 5376 On ch=1 n=67 v=90 - # 6027 Off ch=1 n=67 v=90 - # 6144 On ch=1 n=64 v=90 - # 6469 Off ch=1 n=64 v=90 - # 6528 On ch=1 n=62 v=90 - # 6853 Off ch=1 n=62 v=90 - caitlib.put_note_on(self.m_seq, self.m_port1, 5376*m, 0, 67, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 6027*m, 0, 67, 90) - caitlib.put_note_on(self.m_seq, self.m_port1, 6144*m, 0, 64, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 6469*m, 0, 64, 90) - caitlib.put_note_on(self.m_seq, self.m_port1, 6528*m, 0, 62, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 6853*m, 0, 62, 90) - - # 6912 On ch=1 n=60 v=90 - # 7237 Off ch=1 n=60 v=90 - # 7296 On ch=1 n=62 v=90 - # 7621 Off ch=1 n=62 v=90 - # 7680 On ch=1 n=64 v=90 - # 8005 Off ch=1 n=64 v=90 - caitlib.put_note_on(self.m_seq, self.m_port1, 6912*m, 0, 60, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 7237*m, 0, 60, 90) - caitlib.put_note_on(self.m_seq, self.m_port1, 7296*m, 0, 62, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 7621*m, 0, 62, 90) - caitlib.put_note_on(self.m_seq, self.m_port1, 7680*m, 0, 64, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 8005*m, 0, 64, 90) - - # 8064 On ch=1 n=64 v=90 - # 8389 Off ch=1 n=64 v=90 - # 8448 On ch=1 n=64 v=90 - # 9099 Off ch=1 n=64 v=90 - # 9216 On ch=1 n=62 v=90 - # 9541 Off ch=1 n=62 v=90 - caitlib.put_note_on(self.m_seq, self.m_port1, 8064*m, 0, 64, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 8389*m, 0, 64, 90) - caitlib.put_note_on(self.m_seq, self.m_port1, 8448*m, 0, 64, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 9099*m, 0, 64, 90) - caitlib.put_note_on(self.m_seq, self.m_port1, 9216*m, 0, 62, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 9541*m, 0, 62, 90) - - # 9600 On ch=1 n=62 v=90 - # 9925 Off ch=1 n=62 v=90 - # 9984 On ch=1 n=64 v=90 - # 10309 Off ch=1 n=64 v=90 - # 10368 On ch=1 n=62 v=90 - # 10693 Off ch=1 n=62 v=90 - caitlib.put_note_on(self.m_seq, self.m_port1, 9600*m, 0, 62, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 9925*m, 0, 62, 90) - caitlib.put_note_on(self.m_seq, self.m_port1, 9984*m, 0, 64, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 10309*m, 0, 64, 90) - caitlib.put_note_on(self.m_seq, self.m_port1, 10368*m, 0, 62, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 10693*m, 0, 62, 90) - - # 10752 On ch=1 n=60 v=90 - # 12056 Off ch=1 n=60 v=90 - caitlib.put_note_on(self.m_seq, self.m_port1, 10752*m, 0, 60, 90) - caitlib.put_note_off(self.m_seq, self.m_port1, 12056*m, 0, 60, 90) + self.m_seq = CailibInstance("Caitlyn") + + if self.m_seq.isOk(): + self.m_port1 = self.m_seq.createPort("out1") + + m = 44 + + self.m_port1.addControl(0*m, 0, 7, 99) + self.m_port1.addControl(0*m, 0, 10, 63) + self.m_port1.addProgram(0*m, 0, 0, 0) + + # 0 On ch=1 n=64 v=90 + # 325 Off ch=1 n=64 v=90 + # 384 On ch=1 n=62 v=90 + # 709 Off ch=1 n=62 v=90 + # 768 On ch=1 n=60 v=90 + # 1093 Off ch=1 n=60 v=90 + self.m_port1.addNote( 0*m, 0, 64, 90, 325*m) + self.m_port1.addNote(384*m, 0, 62, 90, 325*m) + self.m_port1.addNote(768*m, 0, 60, 90, 325*m) + + # 1152 On ch=1 n=62 v=90 + # 1477 Off ch=1 n=62 v=90 + # 1536 On ch=1 n=64 v=90 + # 1861 Off ch=1 n=64 v=90 + # 1920 On ch=1 n=64 v=90 + # 2245 Off ch=1 n=64 v=90 + self.m_port1.addNote(1152*m, 0, 62, 90, 325*m) + self.m_port1.addNote(1536*m, 0, 64, 90, 325*m) + self.m_port1.addNote(1920*m, 0, 64, 90, 325*m) + + # 2304 On ch=1 n=64 v=90 + # 2955 Off ch=1 n=64 v=90 + # 3072 On ch=1 n=62 v=90 + # 3397 Off ch=1 n=62 v=90 + # 3456 On ch=1 n=62 v=90 + # 3781 Off ch=1 n=62 v=90 + self.m_port1.addNote(2304*m, 0, 64, 90, 650*m) + self.m_port1.addNote(3072*m, 0, 62, 90, 325*m) + self.m_port1.addNote(3456*m, 0, 62, 90, 325*m) + + # 3840 On ch=1 n=62 v=90 + # 4491 Off ch=1 n=62 v=90 + # 4608 On ch=1 n=64 v=90 + # 4933 Off ch=1 n=64 v=90 + # 4992 On ch=1 n=67 v=90 + # 5317 Off ch=1 n=67 v=90 + self.m_port1.addNote(3840*m, 0, 62, 90, 650*m) + self.m_port1.addNote(4608*m, 0, 64, 90, 325*m) + self.m_port1.addNote(4992*m, 0, 67, 90, 325*m) + + # 5376 On ch=1 n=67 v=90 + # 6027 Off ch=1 n=67 v=90 + # 6144 On ch=1 n=64 v=90 + # 6469 Off ch=1 n=64 v=90 + # 6528 On ch=1 n=62 v=90 + # 6853 Off ch=1 n=62 v=90 + self.m_port1.addNote(5376*m, 0, 67, 90, 650*m) + self.m_port1.addNote(6144*m, 0, 64, 90, 325*m) + self.m_port1.addNote(6528*m, 0, 62, 90, 325*m) + + # 6912 On ch=1 n=60 v=90 + # 7237 Off ch=1 n=60 v=90 + # 7296 On ch=1 n=62 v=90 + # 7621 Off ch=1 n=62 v=90 + # 7680 On ch=1 n=64 v=90 + # 8005 Off ch=1 n=64 v=90 + self.m_port1.addNote(6912*m, 0, 60, 90, 325*m) + self.m_port1.addNote(7296*m, 0, 62, 90, 325*m) + self.m_port1.addNote(7680*m, 0, 64, 90, 325*m) + + # 8064 On ch=1 n=64 v=90 + # 8389 Off ch=1 n=64 v=90 + # 8448 On ch=1 n=64 v=90 + # 9099 Off ch=1 n=64 v=90 + # 9216 On ch=1 n=62 v=90 + # 9541 Off ch=1 n=62 v=90 + self.m_port1.addNote(8064*m, 0, 64, 90, 325*m) + self.m_port1.addNote(8448*m, 0, 64, 90, 650*m) + self.m_port1.addNote(9216*m, 0, 62, 90, 325*m) + + # 9600 On ch=1 n=62 v=90 + # 9925 Off ch=1 n=62 v=90 + # 9984 On ch=1 n=64 v=90 + # 10309 Off ch=1 n=64 v=90 + # 10368 On ch=1 n=62 v=90 + # 10693 Off ch=1 n=62 v=90 + self.m_port1.addNote(9600*m, 0, 62, 90, 325*m) + self.m_port1.addNote(9984*m, 0, 64, 90, 325*m) + self.m_port1.addNote(10368*m, 0, 62, 90, 325*m) + + # 10752 On ch=1 n=60 v=90 + # 12056 Off ch=1 n=60 v=90 + self.m_port1.addNote(10752*m, 0, 60, 90, 650*m) def saveSettings(self): self.settings.setValue("Geometry", self.saveGeometry()) @@ -231,8 +206,8 @@ class CaitlynMainW(QMainWindow, ui_caitlyn.Ui_CaitlynMainW): } def closeEvent(self, event): - if self.m_seq: - caitlib.close(self.m_seq) + if self.m_seq.isOk(): + self.m_seq.close() self.scene.removeItem(self.item1) self.saveSettings()