Added working midi devices events handling on server computer

This commit is contained in:
sam 2020-04-22 01:05:50 +02:00
parent c57c2f1715
commit 6f53bfb3b8
4 changed files with 158 additions and 47 deletions

View File

@ -26,10 +26,7 @@ import json
from rtmidi.midiconstants import (CHANNEL_PRESSURE, CONTROLLER_CHANGE, NOTE_ON, NOTE_OFF,
PITCH_BEND, POLY_PRESSURE, PROGRAM_CHANGE)
import midi3
# from websocket_server import WebsocketServer
#import socket
import types, time
import types
import websocket
@ -68,6 +65,8 @@ else:
print("Default device enabled")
defaultdevice = True
#
# Midi part
#
@ -75,10 +74,6 @@ else:
# default local MIDI device
nozmidi = "BCR2000 Port 1"
# nozmidi = "Arturia BeatStep"
# nozmidi = "Virtual Midi A"
# nozmidi = "Virtual Sequencer"
# nowmidi = "IAC Driver Sequencer Bus 1"
# nozmidi = "UM-ONE:UM-ONE MIDI 1 20:0"
midichanOCS2 = 2
@ -97,7 +92,7 @@ def GetTime():
#
# Settings from clientruler.json
# Settings from rules.json
#
# Load midi routing definitions in clientruler.json
@ -111,8 +106,6 @@ def LoadMidiRules():
MidiRules = json.loads(s)
# return midi rulename number for given type 'Specials', 'cc2cc'
def findMidiRules(rulename,ruletype):
@ -124,6 +117,8 @@ def findMidiRules(rulename,ruletype):
position = counter
return position
#
# Settings from jamidi.json
#
@ -139,7 +134,6 @@ def LoadConfs():
Confs = json.loads(s)
# return midi confname number for given type 'Specials', 'cc2cc'
def findConfs(confname,conftype):
@ -233,6 +227,9 @@ def reset(nozoid):
crtvalueOCS2[ccnumber]=resetOCS2[ccnumber]
print("End of reset for", nozoid)
print("")
#
# Websocket part
#
@ -264,8 +261,10 @@ def on_open(ws):
_thread.start_new_thread(run, ())
def on_message(ws, message):
#
print("")
print(message)
if len(message) > 200:
@ -274,15 +273,20 @@ def on_message(ws, message):
oscpath = message.split(" ")
if debug > 0:
#print "Client got from WS", client['id'], "said :", message, "splitted in an oscpath :", oscpath
print("clientruler got from WS :", message, "splitted in an oscpath :", oscpath)
print("client got from WS :", message, "splitted in an oscpath :", oscpath)
wscommand = oscpath[0].split("/")
print("WS command was :",wscommand)
# debug
if debug > 0:
print("wscommand :",wscommand)
# noarg
if len(oscpath) == 1:
args[0] = "noargs"
#print "noargs command"
# CC : /device/cc/2 127
elif wscommand[1] == "ocs2":
if wscommand[2] == "cc":
print("Incoming OCS-2 WS CC", wscommand[3], ":", int(oscpath[1]))
@ -301,17 +305,33 @@ def on_message(ws, message):
print("Incoming MMO-3 WS OSC1", wscommand[3], ":", int(oscpath[1]))
# RESET : /device/reset 1
elif wscommand[2] == "reset":
if wscommand[1] == "ocs2":
reset("ocs2")
else:
reset("mmo3")
# NOTEON : /device/noteon note velocity
elif wscommand[2] == "noteon":
midi3.NoteOn(int(oscpath[1]), int(oscpath[2]), Confs[wscommand[1]][0]["mididevice"])
# NOTEOFF /device/noteoff note
elif wscommand[2] == "noteoff":
midi3.NoteOff(int(oscpath[1]), Confs[wscommand[1]][0]["mididevice"])
# if needed a loop back : WS Client -> server -> WS Client
# sendWSall(message)
#
# Running...
#
LoadMidiRules()
LoadConfs()
@ -335,10 +355,9 @@ try:
on_close = on_close)
midi3.ws = ws
midi3.wsmode = True
midi3.clientmode = True
print("Midi Configuration...")
midi3.check()
ws.on_open = on_open

44
main.py
View File

@ -11,8 +11,6 @@ print("")
print("Jamidi Server")
print("v0.1b")
#from multiprocessing import Process, Queue, TimeoutError
#import subprocess
import sys
import traceback
import os
@ -24,7 +22,7 @@ import midi3
from websocket_server import WebsocketServer
#import socket
import types, time, json
import types, json
import argparse
debug = 1
@ -85,7 +83,6 @@ Players=0
# Midi part
#
print("Midi Configuration...")
# print("Midi Destination", nozmidi)
@ -95,7 +92,6 @@ def GetTime():
return time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())
# /cc cc number value
def cc(midichannel, ccnumber, value, mididest):
@ -137,6 +133,7 @@ def sendallcurrentccvalues(nozoid):
else:
for ccnumber in range(0,32):
sendWSall("/ocs2/cc/"+str(ccnumber)+" "+str(crtvalueOCS2[ccnumber]))
#
# Settings from jamidi.json
#
@ -212,16 +209,22 @@ def message_received(client, wserver, message):
else:
print(GetTime(),"Main got WS Client", client['id'], "said :", message)
# wscommand will be like ['', 'ocs2', 'cc', '9']
wscommand = oscpath[0].split("/")
# debug
if debug > 0:
print("wscommand :",wscommand)
# noarg
if len(oscpath) == 1:
args[0] = "noargs"
#print "noargs command"
# like /ocs2/cc/2 127
# CC : /device/cc/2 127
elif wscommand[2] == "cc":
ccvr=int(wscommand[3]) #cc variable
ccvl=int(oscpath[1]) #cc value
@ -236,22 +239,31 @@ def message_received(client, wserver, message):
cc(Confs[wscommand[1]][0]["midichan"], ccvr, ccvl, Confs[wscommand[1]][0]["mididevice"])
# like /ocs2/reset 1
# RESET : /device/reset 1
elif wscommand[2] == "reset":
if wscommand[1] == "ocs2":
reset("ocs2")
else:
reset("mmo3")
#print ""
# NOTEON : /device/noteon note velocity
elif wscommand[2] == "noteon":
midi3.NoteOn(int(oscpath[1]), int(oscpath[2]), Confs[wscommand[1]][0]["mididevice"])
# NOTEOFF /device/noteoff note
elif wscommand[2] == "noteoff":
midi3.NoteOff(int(oscpath[1]), Confs[wscommand[1]][0]["mididevice"])
ws.send("/noteon "+str(msg[1])+" "+str(msg[2]))
# if needed a loop back : WS Client -> server -> WS Client
# Loop back : WS Client -> server -> WS Client
sendWSall(message)
'''
def handle_timeout(self):
self.timed_out = True
'''
def sendWSall(message):
@ -262,6 +274,11 @@ def sendWSall(message):
wserver.send_message_to_all(message)
#
# Running...
#
LoadConfs()
serverIP = Confs[servername][0]["IP"]
@ -275,6 +292,7 @@ try:
# Websocket startup
wserver = WebsocketServer(wsPORT,host=serverIP)
midi3.ws = wserver
#print wserver
print("")

100
midi3.py
View File

@ -60,7 +60,7 @@ midinputs = []
debug = 0
# False = server / True = Client
wsmode = False
clientmode = False
#Mser = False
@ -110,6 +110,15 @@ def midi2note(midinote):
print("midinote",midinote, "note", notes[midinote%12]+str(round(midinote/12)))
return notes[midinote%12]+str(round(midinote/12))
# Send through websocket.
# Different websocket library for client (websocket) or server (websocket_server.
# ws object is added here by main.py or client.py startup : midi3.ws =
def wssend(message):
if clientmode == True:
ws.send(message)
else:
ws.send_message_to_all(msg = message)
#
# MIDI Startup and handling
@ -139,8 +148,11 @@ def MidinProcess(inqueue, portname):
MidiNote = msg[1]
MidiVel = msg[2]
print("NOTE ON :", MidiNote, 'velocity :', MidiVel, "Channel", MidiChannel)
#NoteOn(msg[1],msg[2],mididest)
wssend("/noteon "+str(msg[1])+" "+str(msg[2]))
'''
# Sampler mode : note <63 launch snare.wav / note > 62 kick.wav
if MidiNote < 63 and MidiVel >0:
if platform == 'darwin':
@ -155,36 +167,93 @@ def MidinProcess(inqueue, portname):
os.system("afplay kick.wav")
else:
os.system("aplay kick.wav")
'''
# Note Off
if msg[0]==NOTE_OFF:
print("NOTE OFF :", MidiNote, 'velocity :', MidiVel, "Channel", MidiChannel)
#NoteOff(msg[1],msg[2], mididest)
wssend("/noteoff "+str(msg[1]))
# MMO-3 Midi CC message CHANNEL 1
if msg[0] == CONTROLLER_CHANGE:
print("channel 1 (MMO-3) CC :", msg[1], msg[2])
print("Midi in process send /mmo3/cc/"+str(msg[1])+" "+str(msg[2])+" to WS")
if wsmode == True:
ws.send("/mmo3/cc/"+str(msg[1])+" "+str(msg[2]))
wssend("/mmo3/cc/"+str(msg[1])+" "+str(msg[2]))
# OCS-2 Midi CC message CHANNEL 2
if msg[0] == CONTROLLER_CHANGE+1:
print("channel 2 (OCS-2) CC :", msg[1], msg[2])
print("Midi in process send /ocs2/cc/"+str(msg[1])+" "+str(msg[2])+" to WS")
if wsmode == True:
ws.send("/ocs2/cc/"+str(msg[1])+" "+str(msg[2]))
wssend("/ocs2/cc/"+str(msg[1])+" "+str(msg[2]))
# other midi message
if msg[0] != NOTE_OFF and msg[0] != NOTE_ON and msg[0] != CONTROLLER_CHANGE:
pass
'''
print("from", portname,"other midi message")
MidiMsg(msg[0],msg[1],msg[2],mididest)
'''
def NoteOn(note,color, mididest):
global MidInsNumber
for port in range(MidInsNumber):
# To mididest
if midiname[port].find(mididest) == 0:
midiport[port].send_message([NOTE_ON, note, color])
# To All
elif mididest == "all" and midiname[port].find(mididest) != 0 and midiname[port].find(BhorealMidiName) != 0 and midiname[port].find(LaunchMidiName) != 0:
midiport[port].send_message([NOTE_ON, note, color])
'''
# To Launchpad, if present.
elif mididest == "launchpad" and midiname[port].find(LaunchMidiName) == 0:
launchpad.PadNoteOn(note%64,color)
# To Bhoreal, if present.
elif mididest == "bhoreal" and midiname[port].find(BhorealMidiName) == 0:
gstt.BhorLeds[note%64]=color
midiport[port].send_message([NOTE_ON, note%64, color])
#bhorosc.sendosc("/bhoreal", [note%64 , 0])
'''
def NoteOff(note, mididest):
global MidInsNumber
for port in range(MidInsNumber):
# To mididest
if midiname[port].find(mididest) != -1:
midiport[port].send_message([NOTE_OFF, note, 0])
# To All
elif mididest == "all" and midiname[port].find(mididest) == -1 and midiname[port].find(BhorealMidiName) == -1 and midiname[port].find(LaunchMidiName) == -1:
midiport[port].send_message([NOTE_OFF, note, 0])
'''
# To Launchpad, if present.
elif mididest == "launchpad" and midiname[port].find(LaunchMidiName) == 0:
launchpad.PadNoteOff(note%64)
# To Bhoreal, if present.
elif mididest == "bhoreal" and midiname[port].find(BhorealMidiName) == 0:
midiport[port].send_message([NOTE_OFF, note%64, 0])
gstt.BhorLeds[note%64] = 0
#bhorosc.sendosc("/bhoreal", [note%64 , 0])
'''
# Generic call back : new msg forwarded to queue
@ -340,9 +409,14 @@ def InConfig():
print("")
print("MIDIin...")
# client mode
if wsmode == True:
print("ws object", ws)
if debug > 0:
if clientmode == True:
print("midi3 in client mode")
else:
print("midi3 in server mode")
print("List and attach to available devices on host with OUT port :")
if platform == 'darwin':
@ -458,7 +532,7 @@ def MidiMsg(midimsg, mididest):
print("mididest",mididest, ": ** This midi destination doesn't exists **")
# send midi msg over ws.
#if wsmode == True:
#if clientmode == True:
# ws.send("/ocs2/cc/1 2")

View File

@ -151,7 +151,7 @@ def on_open(ws):
_thread.start_new_thread(run, ())
def on_message(ws, message):
#
print("")
print(message)
if len(message) > 200:
@ -167,8 +167,8 @@ def on_message(ws, message):
if len(oscpath) == 1:
args[0] = "noargs"
#print "noargs command"
# CC : /device/cc/2 127
elif wscommand[2] == "cc":
if wscommand[1] == "ocs2":
print("Incoming OCS-2 WS")
@ -177,7 +177,7 @@ def on_message(ws, message):
print("Incoming MMO-3 WS")
cc(midichanMMO3, int(wscommand[3]), int(oscpath[1]), nozmidi)
# RESET : /device/reset 1
elif wscommand[2] == "reset":
if wscommand[1] == "ocs2":
reset("ocs2")