diff --git a/README.md b/README.md index 44f7772..256436c 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,12 @@ By Sam Neurohack Display Link, OSC, Artnet and Midi timecodes -Listen on all network interface and midi interfaces +Listen on all network interfaces and midi interfaces OSC port : 9001 -ARTNET Port : 6454 +Artnet Port : 6454 + +Needs timecode, rtmidi, mido * Link @@ -15,15 +17,17 @@ ARTNET Port : 6454 * OSC - - hour:minutes:seconds:ms (from OSC message received /TC1/time/30 '00:00:02:23') - - (https://github.com/hautetechnique/OSCTimeCode.git) + - hour:minutes:seconds:ms (from OSC message received containing /TC like /TC1/time/30 '00:00:02:23') + - Tested against https://github.com/hautetechnique/OSCTimeCode.git -* Artnet (OpTimeCode) +* Artnet - - codetype hours:minutes:seconds:frames + - hours:minutes:seconds:frames codetype + - OpTimeCode + - Tested against lightingapps.de/software/artnetviewer * Midi (Clock) - BPM computed from received clock messages - - MTC https://github.com/jeffmikels/timecode_tools.git + - MTC (quarterframes).Tested against mtc_generate from https://github.com/jeffmikels/timecode_tools.git diff --git a/link.cpython-39-darwin.so b/link.cpython-39-darwin.so deleted file mode 100755 index 85d3561..0000000 Binary files a/link.cpython-39-darwin.so and /dev/null differ diff --git a/midix.py b/midix.py index e92f016..5adee86 100644 --- a/midix.py +++ b/midix.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- """ -Midi3 light version for soundt/Jamidi/clapt +Midix light version v0.7.0 Midi Handler : @@ -22,10 +22,11 @@ from threading import Thread import rtmidi from rtmidi.midiutil import open_midiinput -from rtmidi.midiconstants import (CHANNEL_PRESSURE, CONTROLLER_CHANGE, NOTE_ON, NOTE_OFF, +from rtmidi.midiconstants import (CHANNEL_PRESSURE, CONTROLLER_CHANGE, NOTE_ON, NOTE_OFF, SYSTEM_EXCLUSIVE, MIDI_TIME_CODE, PITCH_BEND, POLY_PRESSURE, PROGRAM_CHANGE, TIMING_CLOCK, SONG_CONTINUE, SONG_START, SONG_STOP) import mido from mido import MidiFile +import tools import traceback import weakref @@ -71,6 +72,10 @@ stop = mido.Message(type ="stop") ccontinue = mido.Message(type ="continue") reset = mido.Message(type ="reset") songpos = mido.Message(type ="songpos") +qframe = mido.Message(type = 'quarter_frame') +sysex = mido.Message(type = 'sysex') + +print(SYSTEM_EXCLUSIVE, MIDI_TIME_CODE) #mode = "maxwell" @@ -142,7 +147,7 @@ bpm = 0 running = True samples = deque() last_clock = None - +quarter_frames = [0,0,0,0,0,0,0,0] # # Events from Generic MIDI Handling @@ -251,6 +256,24 @@ def MidinProcess(inqueue, portname): #print("Midi in process send /aurora/stop") SendTCview("/stop",[]) + if msg[0] == SYSTEM_EXCLUSIVE: + # check to see if this is a timecode frame + if len(msg) == 8 and msg[0:4] == [127,127,1,1]: + data = message.data[4:] + tc = tools.mtc_decode(data) + print('FF:',tc) + + + + # https://en.wikipedia.org/wiki/MIDI_timecode + if msg[0] == MIDI_TIME_CODE: + frame_type = (msg[1] >> 4) & 0xF + quarter_frames[frame_type] = msg[1] & 15 + if frame_type == 7: + tc = tools.mtc_decode_quarter_frames(quarter_frames) + print('QF:',tc) + SendTCview("/MIDIQF",[str(tc)]) + ''' # other midi message if msg[0] != NOTE_OFF and msg[0] != NOTE_ON and msg[0] != CONTROLLER_CHANGE: diff --git a/tcview.py b/tcview.py index d13a109..badb21a 100644 --- a/tcview.py +++ b/tcview.py @@ -59,6 +59,11 @@ bpm = 120 ccs =[0]*10 +tkred = "#FFF0F0" +tkgreen = "#F0FFF0" +tkblue = "#F0F0FF" +tktitle =('Arial', 11) +tkfont =('Verdana', 18) # # OSC @@ -127,7 +132,7 @@ def OSC_Stop(): oscserver.close() -# default handler +# OSC default handler def handler(path, tags, args, source): oscaddress = ''.join(path.split("/")) @@ -150,7 +155,12 @@ def handler(path, tags, args, source): if path.find('/MIDIBPM') > -1: #print("midibpm", args) - interface.update_midibpm("BPM " +str(args[0])) + interface.update_midibpm(str(args[0])+" bpm") + + if path.find('/MIDIQF') > -1: + + #print("midimtc", args) + interface.update_midimtc(str(args[0])) # Dcode OSC Timecode /TC1/time/30 "00:01:07:12" or /TC2/time/30 "00:01:07:12" @@ -205,8 +215,8 @@ def BeatEvent(): # new beat ? if int(phase) != prevphase: prevphase = int(phase) - interface.update_link("Beat "+str(beats_str)+" "+str(phase_str)) - interface.update_linkbpm("BPM "+str(bpm)) + interface.update_link(str(beats_str)+" "+str(phase_str)) + interface.update_linkbpm(str(bpm)+" bpm") #sys.stdout.write("Beat "+str(beats_str) + ' \r') #sys.stdout.flush() currentbeat = float(beats_str) @@ -329,7 +339,7 @@ def artnetHandler(data): codetype = data[18] print("OptimeCode : hours", hours, "minutes", minutes, "seconds", seconds, "frames", frames,"type", codetypes[codetype]) #motherosc.send('/artnet/timecode', str(hours)+ ":"+str(minutes)+ ":"+ str(seconds)+ ":"+str(frames)+" timecode type "+str(codetype)) - interface.update_artnetcode(codetypes[codetype]+" "+str(hours)+ ":"+str(minutes)+ ":"+ str(seconds)+ ":"+str(frames)) + interface.update_artnetcode(str(hours)+ ":"+str(minutes)+ ":"+ str(seconds)+ ":"+str(frames)+" "+codetypes[codetype]) if data[8] == 0x00 and data[9] == 0x98: print("OpTimeSync") @@ -364,55 +374,61 @@ class Interface(Frame): Tous les widgets sont stockés comme attributs de cette fenêtre.""" def __init__(self, myframe, **kwargs): - Frame.__init__(self, myframe, width=300, height=576, bg="black", **kwargs) + Frame.__init__(self, myframe, width=350, height=576, bg="black", **kwargs) self.pack(fill=NONE) self.nb_clic = 0 # Création de nos widgets - self.message = Label(self, text=" Timecodes viewer ", bg="black", foreground="white") - self.message.place(x = 0, y = 25) - self.message.pack() + #self.message = Label(self, text=" Timecodes viewer ", bg="black", foreground="white") + #self.message.place(x = 0, y = 25) + #self.message.pack() #self.message.config(bg="black", foreground="white") - self.link = Label(self, text="-- Link --", bg="black", foreground="white") + + self.link = Label(self, text="Link", bg="black", foreground="white", font = tktitle, justify ='left') #self.lbl0.place(x = 0, y = 55) self.link.pack() - self.linkbpm = Label(self, text="BPM", bg="black", foreground="white") + self.linkbpm = Label(self, text="..bpm..", bg="black", foreground="white", font = tkfont) #self.lbl0.place(x = 0, y = 55) self.linkbpm.pack() - self.lbl1 = Label(self, text="Waiting...", bg="black", foreground="white") + self.lbl1 = Label(self, text="..beats..", bg="black", foreground="white", font = tkfont) #self.lbl0.place(x = 0, y = 55) self.lbl1.pack() - self.lbl2 = Label(self, text="-- OSC --", bg="black", foreground="white") + self.lbl2 = Label(self, text="OSC", bg="black", foreground=tkblue, font = tktitle, anchor =W) #self.lbl0.place(x = 0, y = 55) self.lbl2.pack() - self.oscode = Label(self, text="Waiting...", bg="black", foreground="white") + self.oscode = Label(self, text="..:..:..:.. ", bg="black", foreground=tkblue, font = tkfont) #self.lbl0.place(x = 0, y = 55) self.oscode.pack() - self.artnet = Label(self, text="-- Artnet --", bg="black", foreground="white") + self.artnet = Label(self, text="Artnet", bg="black", foreground=tkgreen, font = tktitle) #self.lbl0.place(x = 0, y = 55) self.artnet.pack() - self.artnetcode = Label(self, text="Waiting...", bg="black", foreground="white") + self.artnetcode = Label(self, text="..:..:..:..", bg="black", foreground=tkgreen, font = tkfont) #self.lbl0.place(x = 0, y = 55) self.artnetcode.pack() - self.midi = Label(self, text="-- Midi --", bg="black", foreground="white") + self.midi = Label(self, text="Midi", bg="black", foreground=tkred, font = tktitle) #self.lbl0.place(x = 0, y = 55) self.midi.pack() - self.midibpm = Label(self, text="Waiting...", bg="black", foreground="white") + self.midibpm = Label(self, text="... bpm", bg="black", foreground=tkred, font = tkfont) #self.lbl0.place(x = 0, y = 55) self.midibpm.pack() - self.quit_button = Button(self, text="Quit", command=self.quit) + self.midimtc = Label(self, text="..:..:..:..", bg="black", foreground=tkred, font = tkfont) + #self.lbl0.place(x = 0, y = 55) + self.midimtc.pack() + + self.quit_button = Button(self, text="Quit", command=self.quit, font = tktitle) #self.quit_button.configure(background = "green") self.quit_button.pack(side="bottom") self.update_UI() + ''' self.bouton_cliquer = Button(self, text="Cliquez ici", fg="red", command=self.cliquer) @@ -431,6 +447,9 @@ class Interface(Frame): def update_midibpm(self, msg): self.midibpm.configure(text = msg) + def update_midimtc(self, msg): + self.midimtc.configure(text = msg) + def update_artnetcode(self, msg): self.artnetcode.configure(text = msg)