def __init__(self, driver_name="DMX Bridge", universe=0): """ midi->dmx bridge :param driver_name: The midi name of the bridge. This will show up in Logic :param universe: The DMX universe to connect to """ self.driver_name = driver_name self.appname = "{} - {}".format(__appname__, driver_name) # initialize a default dmx frame self.midi_source = MIDIDestination(driver_name) self.frame = [0] * 255 self.universe = universe # this is the starting note for all midi channels self.note_offset = 24 # this is the number of dmx channels per midi channel # each midi channel will support 32 notes. This will allow # 16 fixtures via 16 midi channels. self.dmx_offset = 32 # MacOS X related stuff self.NSUserNotification = objc.lookUpClass('NSUserNotification') self.NSUserNotificationCenter = objc.lookUpClass( 'NSUserNotificationCenter') self.dmx_wrapper = None self.dmx_client = None self.dmx_tick = 100 self.midi_tick = 10 super(Midi2Dmx, self).__init__()
def repeater(): dest = MIDIDestination("repeater input") source = MIDISource("repeater output") frames = [] last_frame_time = time() while True: midi_in = dest.recv() if midi_in: #source.send(midi_in) frames.append((last_frame_time + DELAY, midi_in)) while frames: midi_out = frames[0] if midi_out[0] < last_frame_time: source.send(midi_out[1]) frames.pop(0) else: break now = time() wait_time = -1 while wait_time <= 0: last_frame_time = last_frame_time + LOOP_WAIT wait_time = last_frame_time - now sleep(wait_time)
def ports(cls): print >> sys.stderr, "Available sources:" print >> sys.stderr, " " + "\n ".join([s.name for s in MIDISource.list()]) print >> sys.stderr, "" print >> sys.stderr, "Available destinations:" print >> sys.stderr, " " + "\n ".join([d.name for d in MIDIDestination.list()]) return 1
def __init__(self, driver_name="DMX Bridge", universe=0): """ midi->dmx bridge :param driver_name: The midi name of the bridge. This will show up in Logic :param universe: The DMX universe to connect to """ self.driver_name = driver_name self.appname = "{} - {}".format(__appname__, driver_name) # initialize a default dmx frame self.midi_source = MIDIDestination(driver_name) self.frame = [0] * 255 self.universe = universe # this is the starting note for all midi channels self.note_offset = 24 # this is the number of dmx channels per midi channel # each midi channel will support 32 notes. This will allow # 16 fixtures via 16 midi channels. self.dmx_offset = 32 # MacOS X related stuff self.NSUserNotification = objc.lookUpClass('NSUserNotification') self.NSUserNotificationCenter = objc.lookUpClass('NSUserNotificationCenter') self.dmx_wrapper = None self.dmx_client = None self.dmx_tick = 100 self.midi_tick = 10 super(Midi2Dmx, self).__init__()
def ports(cls): print >> sys.stderr, "Available sources:" print >> sys.stderr, " " + "\n ".join( [s.name for s in MIDISource.list()]) print >> sys.stderr, "" print >> sys.stderr, "Available destinations:" print >> sys.stderr, " " + "\n ".join( [d.name for d in MIDIDestination.list()]) return 1
def find_endpoints(self, source_substring, destination_substring): sources = [s for s in MIDISource.list() if s.name.find(source_substring) != -1] if sources: self.source = sources[0] logger.info("Using \"%s\" as the midi source" % self.source.name) else: raise EndpointError("Unable to find a source with a substring of %s" % source_substring) destinations = [s for s in MIDIDestination.list() if s.name.find(destination_substring) != -1] if destinations: self.destination = destinations[0] logger.info("Using \"%s\" as the midi destination" % self.destination.name) else: raise EndpointError("Unable to find a destination with a substring of %s" % destination_substring)
def find_endpoints(self, source_substring, destination_substring): sources = [ s for s in MIDISource.list() if s.name.find(source_substring) != -1 ] if sources: self.source = sources[0] logger.info("Using \"%s\" as the midi source" % self.source.name) else: raise EndpointError( "Unable to find a source with a substring of %s" % source_substring) destinations = [ s for s in MIDIDestination.list() if s.name.find(destination_substring) != -1 ] if destinations: self.destination = destinations[0] logger.info("Using \"%s\" as the midi destination" % self.destination.name) else: raise EndpointError( "Unable to find a destination with a substring of %s" % destination_substring)
import os.path import sys __dir__ = os.path.dirname(__file__) sys.path.append(os.path.join(__dir__, '..')) from simplecoremidi import MIDIDestination, MIDISource, NoteOnMessage, NoteOffMessage from time import sleep NOTE_ON = 0x90 channel = 1 MIDDLE_C = 60 for d in MIDIDestination.list(): print("send message to %s" % d.name) d.send(NoteOnMessage(channel, MIDDLE_C, 127)) sleep(1) d.send(NoteOffMessage(channel, MIDDLE_C).asNoteOn()) while (True): for s in MIDISource.list(): message = s.receive(timeout=2) if message == None: sys.stdout.write('.') else: print (s.name, str(message))
import os.path import sys __dir__ = os.path.dirname(__file__) sys.path.append(os.path.join(__dir__, '..')) from simplecoremidi import MIDIDestination, MIDISource, NoteOnMessage, NoteOffMessage from time import sleep NOTE_ON = 0x90 channel = 1 MIDDLE_C = 60 for d in MIDIDestination.list(): print("send message to %s" % d.name) d.send(NoteOnMessage(channel, MIDDLE_C, 127)) sleep(1) d.send(NoteOffMessage(channel, MIDDLE_C).asNoteOn()) while (True): for s in MIDISource.list(): message = s.receive(timeout=2) if message == None: sys.stdout.write('.') else: print(s.name, str(message))
class Midi2Dmx(threading.Thread): def __init__(self, driver_name="DMX Bridge", universe=0): """ midi->dmx bridge :param driver_name: The midi name of the bridge. This will show up in Logic :param universe: The DMX universe to connect to """ self.driver_name = driver_name self.appname = "{} - {}".format(__appname__, driver_name) # initialize a default dmx frame self.midi_source = MIDIDestination(driver_name) self.frame = [0] * 255 self.universe = universe # this is the starting note for all midi channels self.note_offset = 24 # this is the number of dmx channels per midi channel # each midi channel will support 32 notes. This will allow # 16 fixtures via 16 midi channels. self.dmx_offset = 32 # MacOS X related stuff self.NSUserNotification = objc.lookUpClass('NSUserNotification') self.NSUserNotificationCenter = objc.lookUpClass('NSUserNotificationCenter') self.dmx_wrapper = None self.dmx_client = None self.dmx_tick = 100 self.midi_tick = 10 super(Midi2Dmx, self).__init__() def run(self): """Start up the service safely""" self.initialize() if self.dmx_wrapper: self.dmx_wrapper.Run() def stop(self): """Stop the service safely""" if self.dmx_wrapper: self.notify("Stopping...", "Stopping the DMX Bridge. Midi Events " "will NOT be sent to the DMX device") self.dmx_wrapper.Stop() else: self.notify("DMX is not running", "Stop command issued to an inactive " "DMX bridge.") def initialize(self): """ Zero out dmx, set up events """ try: self.dmx_wrapper = ClientWrapper() self.dmx_client = self.dmx_wrapper.Client() except: self.notify("OLAD is not running", "Attept to connect to OLAD failed. " "Please start it and try again.") return self.dmx_wrapper.AddEvent(self.dmx_tick, self.send_to_dmx) self.dmx_wrapper.AddEvent(self.dmx_tick/2, self.get_midi_data) def notify(self, subtitle, info_text): """Send an os x notification""" title = "{} - Universe {}".format(self.appname, self.universe) rumps.notification(title,subtitle,info_text,sound=False) def dmx_frame_sent(self, state): """SendDMX callback""" if not state.Succeeded(): self.dmx_wrapper.Stop() def send_to_dmx(self): """Send the frame to the uDMX device""" self.dmx_wrapper.AddEvent(self.dmx_tick, self.send_to_dmx) dmx_frame = self.build_dmx_frame() self.dmx_client.SendDmx(self.universe, dmx_frame, self.dmx_frame_sent) def update_frame(self, channel, note, velocity): """Translate midi note to dmx channel and velocity to value""" value = velocity * 2 dmx_channel = (note - self.note_offset) + ((channel - 1) * self.dmx_offset) self.frame[dmx_channel] = value def build_dmx_frame(self): """Translate our internal frame structure into a proper dmx frame""" dmx_frame = array.array("B") for frame_channel in self.frame: dmx_frame.append(frame_channel) return dmx_frame def get_midi_data(self): """Get midi data from the midi source""" self.dmx_wrapper.AddEvent(self.dmx_tick, self.get_midi_data) midi_data = self.midi_source.recv() if len(midi_data) > 0: print midi_data for s in split_seq(midi_data, 3): self.parse_midi_data(s) def parse_midi_data(self, midi_data): """Parse the midi data""" # we're going to ignore non-note traffic # sysex data and such. note_on = False modifier = 0 midi_channel = midi_data[0] if midi_channel in range(144, 159): modifier = 143 note_on = True if midi_channel in range(128, 143): modifier = 127 note_on = False if midi_channel in range(144, 159) or midi_channel in range(128, 143): channel = midi_channel - modifier note = midi_data[1] # make sure our velocity is '0' for the note-off # event. if note_on: velocity = midi_data[2] else: velocity = 0 self.update_frame(channel, note, velocity)
class Midi2Dmx(threading.Thread): def __init__(self, driver_name="DMX Bridge", universe=0): """ midi->dmx bridge :param driver_name: The midi name of the bridge. This will show up in Logic :param universe: The DMX universe to connect to """ self.driver_name = driver_name self.appname = "{} - {}".format(__appname__, driver_name) # initialize a default dmx frame self.midi_source = MIDIDestination(driver_name) self.frame = [0] * 255 self.universe = universe # this is the starting note for all midi channels self.note_offset = 24 # this is the number of dmx channels per midi channel # each midi channel will support 32 notes. This will allow # 16 fixtures via 16 midi channels. self.dmx_offset = 32 # MacOS X related stuff self.NSUserNotification = objc.lookUpClass('NSUserNotification') self.NSUserNotificationCenter = objc.lookUpClass( 'NSUserNotificationCenter') self.dmx_wrapper = None self.dmx_client = None self.dmx_tick = 100 self.midi_tick = 10 super(Midi2Dmx, self).__init__() def run(self): """Start up the service safely""" self.initialize() if self.dmx_wrapper: self.dmx_wrapper.Run() def stop(self): """Stop the service safely""" if self.dmx_wrapper: self.notify( "Stopping...", "Stopping the DMX Bridge. Midi Events " "will NOT be sent to the DMX device") self.dmx_wrapper.Stop() else: self.notify("DMX is not running", "Stop command issued to an inactive " "DMX bridge.") def initialize(self): """ Zero out dmx, set up events """ try: self.dmx_wrapper = ClientWrapper() self.dmx_client = self.dmx_wrapper.Client() except: self.notify( "OLAD is not running", "Attept to connect to OLAD failed. " "Please start it and try again.") return self.dmx_wrapper.AddEvent(self.dmx_tick, self.send_to_dmx) self.dmx_wrapper.AddEvent(self.dmx_tick / 2, self.get_midi_data) def notify(self, subtitle, info_text): """Send an os x notification""" title = "{} - Universe {}".format(self.appname, self.universe) rumps.notification(title, subtitle, info_text, sound=False) def dmx_frame_sent(self, state): """SendDMX callback""" if not state.Succeeded(): self.dmx_wrapper.Stop() def send_to_dmx(self): """Send the frame to the uDMX device""" self.dmx_wrapper.AddEvent(self.dmx_tick, self.send_to_dmx) dmx_frame = self.build_dmx_frame() self.dmx_client.SendDmx(self.universe, dmx_frame, self.dmx_frame_sent) def update_frame(self, channel, note, velocity): """Translate midi note to dmx channel and velocity to value""" value = velocity * 2 dmx_channel = (note - self.note_offset) + ( (channel - 1) * self.dmx_offset) self.frame[dmx_channel] = value def build_dmx_frame(self): """Translate our internal frame structure into a proper dmx frame""" dmx_frame = array.array("B") for frame_channel in self.frame: dmx_frame.append(frame_channel) return dmx_frame def get_midi_data(self): """Get midi data from the midi source""" self.dmx_wrapper.AddEvent(self.dmx_tick, self.get_midi_data) midi_data = self.midi_source.recv() if len(midi_data) > 0: print midi_data for s in split_seq(midi_data, 3): self.parse_midi_data(s) def parse_midi_data(self, midi_data): """Parse the midi data""" # we're going to ignore non-note traffic # sysex data and such. note_on = False modifier = 0 midi_channel = midi_data[0] if midi_channel in range(144, 159): modifier = 143 note_on = True if midi_channel in range(128, 143): modifier = 127 note_on = False if midi_channel in range(144, 159) or midi_channel in range(128, 143): channel = midi_channel - modifier note = midi_data[1] # make sure our velocity is '0' for the note-off # event. if note_on: velocity = midi_data[2] else: velocity = 0 self.update_frame(channel, note, velocity)