Added UDP connector for ORCA Livecoding !!
This commit is contained in:
parent
012bef55b1
commit
b79a3487eb
67
README.md
67
README.md
@ -4,7 +4,7 @@ By llstr, Sam Neurohack
|
|||||||
|
|
||||||
LICENCE : CC NC
|
LICENCE : CC NC
|
||||||
|
|
||||||
Midi and more exchanges over LAN/Internet
|
Midi and more exchanges over LAN/Internet. Now with ORCA live coding support !!
|
||||||
|
|
||||||
Imagine Bob own a TR 808 at home and Alice a nozoid OCS-2. They can control each other devices in a webpage or a midi controller.
|
Imagine Bob own a TR 808 at home and Alice a nozoid OCS-2. They can control each other devices in a webpage or a midi controller.
|
||||||
If John has a mutliple encoders midi controller at home and want to control Alice and Bob devices, all changes made by John will be displayed to everyone and played by devices.
|
If John has a mutliple encoders midi controller at home and want to control Alice and Bob devices, all changes made by John will be displayed to everyone and played by devices.
|
||||||
@ -25,6 +25,38 @@ More you can use also a vcvrack complex patch to drive light fixtures, laser abs
|
|||||||
|
|
||||||
- Jamidi is experimental and nowhere safe. Network managment and security is not in jamidi scope. Some ideas : All computers can be on the same encrypted vpn (tinc, zerotier,..). The server can run on a VPS and all client connect to it. The server is at home, closer to midi devices,...
|
- Jamidi is experimental and nowhere safe. Network managment and security is not in jamidi scope. Some ideas : All computers can be on the same encrypted vpn (tinc, zerotier,..). The server can run on a VPS and all client connect to it. The server is at home, closer to midi devices,...
|
||||||
|
|
||||||
|
- Look at jamidi.json for set your configuration. 2 element types : midi device and IP servers
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ORCA livecoding support.
|
||||||
|
|
||||||
|
Livecode some instrument somewhere else. https://github.com/hundredrabbits/Orca
|
||||||
|
|
||||||
|
On computer linked with desired midi instrument :
|
||||||
|
|
||||||
|
python3 main.py
|
||||||
|
|
||||||
|
|
||||||
|
Livecoder should configure ORCA and use it :
|
||||||
|
|
||||||
|
CTRL K ip:ipaddress
|
||||||
|
CTRL K udp:udport (default is 8083)
|
||||||
|
|
||||||
|
MIDI CCs base 36 use ;cmnd
|
||||||
|
|
||||||
|
m : midi channel 0-F (0-15)
|
||||||
|
n : number 0-Z (0-35)
|
||||||
|
d : data 0-Z will output (d/36)*127
|
||||||
|
|
||||||
|
|
||||||
|
MIDI NOTES use ;nmonv
|
||||||
|
|
||||||
|
m : midi channel 0-F (0-15)
|
||||||
|
o : octave 0-8
|
||||||
|
n : Note A-G. For note with # : a-g
|
||||||
|
v : velocity 0-Z will output (v/36)*127
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -55,46 +87,55 @@ Websocket default port is 8081 but one can change.
|
|||||||
|
|
||||||
Will receive all "commands" from all clients, forward them to local devices and broadcast them too.
|
Will receive all "commands" from all clients, forward them to local devices and broadcast them too.
|
||||||
|
|
||||||
|
servername : 'local', 'llstrvpn'. Servers (IP, port,...) must be described in jamidi.json
|
||||||
|
|
||||||
|
How to Run python server :
|
||||||
|
|
||||||
|
python3 main.py
|
||||||
|
|
||||||
Options :
|
Options :
|
||||||
|
|
||||||
servername : 'local', 'llstrvpn'. Servers (IP, port,...) must be described in jamidi.json
|
-h Show this help message and exit
|
||||||
|
|
||||||
--broadcast : Broadcast all incomings commands to all client. Default option.
|
-s SERVERNAME Servername: 'local', 'llstrvpn' (local by default)
|
||||||
|
|
||||||
--no-broadcast : Do not broadcast all incomings commands to all client.
|
-d DEVICENAME Mididevice for incoming ORCA via OSC (mmo3 by default)
|
||||||
|
|
||||||
|
-nocurrent Do not send all current CC values to all new client (enabled by default)
|
||||||
|
|
||||||
--reset : Send reset values to local device at startup. Default option.
|
-nobroadcast Do not broadcast all incomings commands to all client (enabled by default)
|
||||||
|
|
||||||
--no-reset : Do not send reset values to local device at startup.
|
-noreset Do not broadcast all incomings commands to all client (enabled by default)
|
||||||
|
|
||||||
|
-nothrough Disable the builtin midithrough from any midi IN to --device enabled by default
|
||||||
|
|
||||||
--current : Send all current CC values to all new client. Default option.
|
-verbose Enable debug mode (disabled by default)
|
||||||
|
|
||||||
--no-current : Do not send all current CC values to all new client.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# How it work : Clients
|
# How it work : Clients
|
||||||
|
|
||||||
Can be webpages or midi instrument/software. Multiple clients types is supported.
|
Send midi over network to Jamidi. Can be webpages or midi instrument/software. Multiple clients types is supported.
|
||||||
|
|
||||||
|
How to Run python client :
|
||||||
|
|
||||||
|
python3 client.py
|
||||||
|
|
||||||
|
|
||||||
Options :
|
Options :
|
||||||
|
|
||||||
servername : Remote server 'local', 'xrkia' ('local' by default). Servers must be described in jamidi.json
|
servername : Remote server 'local', 'xrkia' ('local' by default). Servers must be described in jamidi.json
|
||||||
|
|
||||||
default : Network <-> default midi device (True or False)
|
-s servername servername: 'local', 'xrkia' ('local' by default)
|
||||||
|
|
||||||
|
-nodefault Do not send reset values to local device a startup.
|
||||||
|
|
||||||
|
|
||||||
Some "rules" are available. Say you want all network incoming midi CC 1 channel 0 goes to a specific device on channel 3 CC 48. Rules must be described in rules.json
|
Some "rules" are available. Say you want all network incoming midi CC 1 channel 0 goes to a specific device on channel 3 CC 48. Rules must be described in rules.json
|
||||||
|
|
||||||
Each rule may happen at all time or only during a "song".
|
Each rule may happen at all time or only during a "song".
|
||||||
|
|
||||||
How to Run python client :
|
|
||||||
|
|
||||||
python3 client.py
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
66
jamidi.json
66
jamidi.json
@ -51,6 +51,19 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
"sam" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"_comment": "Server is laser.teamlaser.fr",
|
||||||
|
"type": "serverconf",
|
||||||
|
"name": "tmlsr",
|
||||||
|
"IP": "192.168.2.43",
|
||||||
|
"port": 8081,
|
||||||
|
"oscport": 8082,
|
||||||
|
"udport": 8083
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
"sq-1": [
|
"sq-1": [
|
||||||
{
|
{
|
||||||
"_comment": "SQ-1 device parameters",
|
"_comment": "SQ-1 device parameters",
|
||||||
@ -89,59 +102,6 @@
|
|||||||
"midichan" : 1,
|
"midichan" : 1,
|
||||||
"xname" : "mmo3"
|
"xname" : "mmo3"
|
||||||
}
|
}
|
||||||
],
|
|
||||||
|
|
||||||
"ocs2bcr": [
|
|
||||||
{
|
|
||||||
"_comment": "OCS-2 control with BCR2000",
|
|
||||||
"type": "mididevice",
|
|
||||||
"mididevice": "BCR2000 Port 1",
|
|
||||||
"midichan" : 2,
|
|
||||||
"xname" : "ocs2"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
"mmo3bcr": [
|
|
||||||
{
|
|
||||||
"_comment": "MMO-3 control with BCR2000",
|
|
||||||
"type": "mididevice",
|
|
||||||
"mididevice": "BCR2000 Port 1",
|
|
||||||
"midichan" : 1,
|
|
||||||
"xname" : "mmo3"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
"launchpad": [
|
|
||||||
{
|
|
||||||
"_comment": "Launchpad mini device parameters",
|
|
||||||
"type": "mididevice",
|
|
||||||
"mididevice": "Launchpad Mini",
|
|
||||||
"midichan" : 0,
|
|
||||||
"xname" : "launchpad"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
"maxwell": [
|
|
||||||
{
|
|
||||||
"_comment": "Mawell device parameters",
|
|
||||||
"type": "mididevice",
|
|
||||||
"mididevice": "to Maxwell 1",
|
|
||||||
"midichan" : 0,
|
|
||||||
"xname" : "ocs2"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
"default": [
|
|
||||||
{
|
|
||||||
"_comment": "Client : default midi device",
|
|
||||||
"type": "mididevice",
|
|
||||||
"mididevice": "BCR2000 Port 1",
|
|
||||||
"midichan" : 3,
|
|
||||||
"xname" : "default"
|
|
||||||
}
|
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
207
libs/OSCom.py
Normal file
207
libs/OSCom.py
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# -*- mode: Python -*-
|
||||||
|
|
||||||
|
'''
|
||||||
|
OSCcom for jamidi v0.1b
|
||||||
|
|
||||||
|
OSCom.Start(serverIP, OSCPORT)
|
||||||
|
default handler : handler(path, tags, args, source)
|
||||||
|
register particular OSC command in Start(): i.e oscserver.addMsgHandler( "/n", Note)
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
import midi3
|
||||||
|
|
||||||
|
#import socket
|
||||||
|
import types, json
|
||||||
|
from OSC3 import OSCServer, OSCClient, OSCMessage
|
||||||
|
import _thread, time
|
||||||
|
import gstt
|
||||||
|
import WScom, UDPcom
|
||||||
|
import midi3
|
||||||
|
|
||||||
|
#base36 = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
|
||||||
|
|
||||||
|
|
||||||
|
def GetTime():
|
||||||
|
return time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())
|
||||||
|
|
||||||
|
# this method of reporting timeouts only works by convention
|
||||||
|
# that before calling handle_request() field .timed_out is
|
||||||
|
# set to False
|
||||||
|
def handle_timeout(self):
|
||||||
|
self.timed_out = True
|
||||||
|
|
||||||
|
|
||||||
|
def Start(serverIP, OSCPORT):
|
||||||
|
global oscserver
|
||||||
|
|
||||||
|
#print(GetTime(),gstt.oscname, gstt.Confs[gstt.oscname][0]["midichan"])
|
||||||
|
#print(gstt.Confs)
|
||||||
|
#print(gstt.Confs[gstt.oscname])
|
||||||
|
for i in range(len(gstt.Confs[gstt.oscname])):
|
||||||
|
print(GetTime(),gstt.oscname, gstt.Confs[gstt.oscname][i]["midichan"])
|
||||||
|
|
||||||
|
oscserver = OSCServer( (serverIP, OSCPORT) )
|
||||||
|
oscserver.timeout = 0
|
||||||
|
# funny python's way to add a method to an instance of a class
|
||||||
|
import types
|
||||||
|
oscserver.handle_timeout = types.MethodType(handle_timeout, oscserver)
|
||||||
|
|
||||||
|
oscserver.addMsgHandler( "default", handler )
|
||||||
|
oscserver.addMsgHandler( "/n", Note)
|
||||||
|
oscserver.addMsgHandler( "/c", CC)
|
||||||
|
oscserver.addMsgHandler( "/p", PB)
|
||||||
|
_thread.start_new_thread(osc_thread, ())
|
||||||
|
|
||||||
|
|
||||||
|
# RAW OSC Frame available ?
|
||||||
|
def OSCframe():
|
||||||
|
# clear timed_out flag
|
||||||
|
oscserver.timed_out = False
|
||||||
|
# handle all pending requests then return
|
||||||
|
while not oscserver.timed_out:
|
||||||
|
oscserver.handle_request()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# OSC server Thread : handler, dacs reports and simulator points sender to UI.
|
||||||
|
def osc_thread():
|
||||||
|
|
||||||
|
|
||||||
|
#print("osc Thread launched")
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
|
||||||
|
time.sleep(0.005)
|
||||||
|
OSCframe()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
import sys, traceback
|
||||||
|
print('\n---------------------')
|
||||||
|
print('Exception: %s' % e)
|
||||||
|
print('- - - - - - - - - - -')
|
||||||
|
traceback.print_tb(sys.exc_info()[2])
|
||||||
|
print("\n")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Properly close the system. Todo
|
||||||
|
def Stop():
|
||||||
|
oscserver.close()
|
||||||
|
|
||||||
|
|
||||||
|
# default handler
|
||||||
|
def handler(path, tags, args, source):
|
||||||
|
|
||||||
|
oscaddress = ''.join(path.split("/"))
|
||||||
|
print()
|
||||||
|
print("Jamidi Default OSC Handler got from " + str(source[0]),"OSC msg", path, "args", args)
|
||||||
|
#print("OSC address", path)
|
||||||
|
#print("find.. /bhoreal ?", path.find('/bhoreal'))
|
||||||
|
if len(args) > 0:
|
||||||
|
#print("with args", args)
|
||||||
|
pass
|
||||||
|
|
||||||
|
'''
|
||||||
|
# for example
|
||||||
|
if path == '/truc':
|
||||||
|
arg1 = args[0]
|
||||||
|
arg2 = args[1])
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
MIDI NOTES
|
||||||
|
=n in ORCA
|
||||||
|
/n in OSC
|
||||||
|
ORCA OSC
|
||||||
|
=nmonv /n m o n v
|
||||||
|
m : midi channel (0-15 / ORCA 0-F)
|
||||||
|
o : octave (0-8 / ORCA 0-7)
|
||||||
|
n : Note A to G
|
||||||
|
v : velocity 0-Z will output (v/36)*127
|
||||||
|
|
||||||
|
'''
|
||||||
|
def Note(path, tags, args, source):
|
||||||
|
|
||||||
|
#print('Note from ORCA received',args)
|
||||||
|
|
||||||
|
midichannel = int(args[0],36)
|
||||||
|
octave = int(args[1],36)
|
||||||
|
note = args[2]
|
||||||
|
velocity = int((int(args[3],36)/36)*127)
|
||||||
|
|
||||||
|
if note.istitle() == True:
|
||||||
|
notename = str(note)+ str(octave)
|
||||||
|
else:
|
||||||
|
notename = str(note)+ "#"+ str(octave)
|
||||||
|
|
||||||
|
if gstt.debug > 0:
|
||||||
|
print("incoming note", note, octave, notename, midi3.note2midi(notename) )
|
||||||
|
|
||||||
|
for mididevice in midi3.findJamDevices(gstt.oscname):
|
||||||
|
midi3.NoteOn(midi3.note2midi(notename), velocity, mididevice)
|
||||||
|
#midi3.NoteOn(int(wspath[1]), int(wspath[2]), gstt.Confs[wscommand[1]][0]["mididevice"])
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
CC
|
||||||
|
=c in ORCA
|
||||||
|
/c in OSC
|
||||||
|
|
||||||
|
ORCA OSC
|
||||||
|
=cmcd /c m n d
|
||||||
|
m : midi channel
|
||||||
|
n : number (0-35 / ORCA 0-Z)
|
||||||
|
d : data 0-Z will output (d/36)*127
|
||||||
|
'''
|
||||||
|
def CC(path, tags, args, source):
|
||||||
|
|
||||||
|
midichannel = int(args[0],36)
|
||||||
|
ccvr = int(args[1],36)
|
||||||
|
ccvl = int((int(args[2],36)/36)*127)
|
||||||
|
|
||||||
|
if gstt.debug > 0:
|
||||||
|
print("ccvr=%d/ccvl=%d"%(ccvr,ccvl))
|
||||||
|
if gstt.oscname == "ocs2":
|
||||||
|
gstt.crtvalueOCS2[ccvr]=ccvl
|
||||||
|
else:
|
||||||
|
gstt.crtvalueMMO3[ccvr]=ccvl
|
||||||
|
|
||||||
|
for mididevice in midi3.findJamDevices(gstt.oscname):
|
||||||
|
midi3.cc(gstt.Confs[gstt.oscname][0]["midichan"], ccvr, ccvl, mididevice)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def PB(path, tags, args, source):
|
||||||
|
|
||||||
|
#print("Pitch number",ccnumber, value)
|
||||||
|
midichannel = int(args[0])
|
||||||
|
ccnumber = int(args[1])
|
||||||
|
ccdata = int(args[3])
|
||||||
|
|
||||||
|
'''
|
||||||
|
# If needed to send some OSC
|
||||||
|
def SendOSC(ip,port,oscaddress,oscargs=''):
|
||||||
|
|
||||||
|
oscmsg = OSCMessage()
|
||||||
|
oscmsg.setAddress(oscaddress)
|
||||||
|
oscmsg.append(oscargs)
|
||||||
|
|
||||||
|
osclient = OSCClient()
|
||||||
|
osclient.connect((ip, port))
|
||||||
|
|
||||||
|
if gstt.debug == True :
|
||||||
|
print("sending OSC message : ", oscmsg, "to", ip, ":", port)
|
||||||
|
|
||||||
|
try:
|
||||||
|
osclient.sendto(oscmsg, (ip, port))
|
||||||
|
oscmsg.clearData()
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
print ('Connection to', ip, 'refused : died ?')
|
||||||
|
return False
|
||||||
|
'''
|
175
libs/UDPcom.py
Normal file
175
libs/UDPcom.py
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# -*- mode: Python -*-
|
||||||
|
|
||||||
|
'''
|
||||||
|
UDPcom for jamidi v0.1b
|
||||||
|
|
||||||
|
UDPcom.Start(serverIP, UDPORT)
|
||||||
|
Handler : udp_thread()
|
||||||
|
|
||||||
|
Read below for :
|
||||||
|
|
||||||
|
- MIDI NOTES use ;nmonv
|
||||||
|
- MIDI CCs use ;cmnd
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
import midi3
|
||||||
|
|
||||||
|
#import socket
|
||||||
|
import types, json
|
||||||
|
import socket
|
||||||
|
import _thread, time
|
||||||
|
import midi3
|
||||||
|
import WScom, OSCom
|
||||||
|
import gstt
|
||||||
|
import time
|
||||||
|
|
||||||
|
#base36 = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
|
||||||
|
|
||||||
|
def GetTime():
|
||||||
|
return time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())
|
||||||
|
|
||||||
|
def udp_thread():
|
||||||
|
|
||||||
|
while True:
|
||||||
|
payload, client_address = sock.recvfrom(1024)
|
||||||
|
udpath = payload.decode('utf_8')
|
||||||
|
if gstt.debug > 1:
|
||||||
|
print(GetTime(),"UDP got", udpath, "from", str(client_address))
|
||||||
|
#print(udpath[0:1], " ",udpath[1:2], " ",udpath[2:3], " ",udpath[3:4], " " )
|
||||||
|
|
||||||
|
if udpath[0:1] == "n":
|
||||||
|
Note(udpath)
|
||||||
|
|
||||||
|
if udpath[0:1] == "c":
|
||||||
|
CC(udpath)
|
||||||
|
|
||||||
|
if udpath[0:1] == "f":
|
||||||
|
FullCC(udpath)
|
||||||
|
|
||||||
|
time.sleep(0.005)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def Start(serverIP, UDPORT):
|
||||||
|
global sock
|
||||||
|
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
server = ( serverIP,UDPORT)
|
||||||
|
sock.bind(server)
|
||||||
|
_thread.start_new_thread(udp_thread, ())
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
MIDI NOTES use ;nmonv
|
||||||
|
|
||||||
|
m : midi channel 0-F (0-15)
|
||||||
|
o : octave 0-8
|
||||||
|
n : Note A-G. For note with # : a-g
|
||||||
|
v : velocity 0-Z will output (v/36)*127
|
||||||
|
|
||||||
|
'''
|
||||||
|
def Note(udpnote):
|
||||||
|
|
||||||
|
if gstt.debug>0:
|
||||||
|
print()
|
||||||
|
print(GetTime(),'UDPNote from ORCA received', udpnote, udpnote[1:1])
|
||||||
|
|
||||||
|
midichannel = int(udpnote[1:2],36)
|
||||||
|
octave = int(udpnote[2:3],36)
|
||||||
|
note = udpnote[3:4]
|
||||||
|
velocity = (int(udpnote[4:5],36)/36)*127
|
||||||
|
|
||||||
|
#if gstt.debug>0:
|
||||||
|
print(GetTime(),'UDPNote from ORCA received:','midichannel:',midichannel,'octave:',octave,'note:',note,'velocity:',velocity)
|
||||||
|
|
||||||
|
|
||||||
|
#if octave < 9 or midichannel < 16 or int(note,36) < 10 or int(note,36) > 16:
|
||||||
|
if octave < 9 and midichannel < 16 and int(note,36) >= 10 and int(note,36) <= 16:
|
||||||
|
|
||||||
|
if note.istitle() == True:
|
||||||
|
notename = str(note.upper())+ str(octave)
|
||||||
|
else:
|
||||||
|
notename = str(note.upper())+ "#"+ str(octave)
|
||||||
|
|
||||||
|
if gstt.debug > 0:
|
||||||
|
print(GetTime(),"Incoming note", notename, "=", midi3.note2midi(notename), "velocity", velocity, "for channel", midichannel)
|
||||||
|
|
||||||
|
|
||||||
|
for mididevice in midi3.findJamDevices(gstt.oscname):
|
||||||
|
midi3.NoteOn(midi3.note2midi(notename), int(velocity), mididevice, midichannel-1)
|
||||||
|
|
||||||
|
# if sending note back to WS users :
|
||||||
|
#WScom.sendWSall("/"+midi3.findJamName(gstt.oscname, midichannel)+"/noteon "+str(midi3.note2midi(notename)))
|
||||||
|
|
||||||
|
else:
|
||||||
|
print(GetTime(),"Note", midichannel, octave, note, velocity,"had offchart parameters.")
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
MIDI CCs base 36 use ;cmnd
|
||||||
|
|
||||||
|
m : midi channel 0-F (0-15)
|
||||||
|
n : number 0-Z (0-35)
|
||||||
|
d : data 0-Z will output (d/36)*127
|
||||||
|
'''
|
||||||
|
def CC(udpcc):
|
||||||
|
|
||||||
|
print()
|
||||||
|
midichannel = int(udpcc[1:2],36)
|
||||||
|
#midichannel = base36.index(udpcc[1:2].upper())
|
||||||
|
ccvr = int(udpcc[2:3],36)
|
||||||
|
ccvl = int((int(udpcc[3:4],36)/36)*127)
|
||||||
|
|
||||||
|
if midichannel < 16:
|
||||||
|
|
||||||
|
if gstt.debug > 0:
|
||||||
|
print(GetTime(),"ccvr=%d/ccvl=%d"%(ccvr,ccvl))
|
||||||
|
|
||||||
|
if gstt.oscname == "ocs2":
|
||||||
|
gstt.crtvalueOCS2[ccvr]=ccvl
|
||||||
|
else:
|
||||||
|
gstt.crtvalueMMO3[ccvr]=ccvl
|
||||||
|
|
||||||
|
for mididevice in midi3.findJamDevices(gstt.oscname):
|
||||||
|
midi3.cc(midichannel, ccvr, ccvl, mididevice)
|
||||||
|
#midi3.cc(gstt.Confs[gstt.oscname][0]["midichan"], ccvr, ccvl, mididevice)
|
||||||
|
WScom.sendWSall("/"+midi3.findJamName(mididevice, midichannel)+"/cc/"+str(ccvr)+" "+str(ccvl))
|
||||||
|
else:
|
||||||
|
print(GetTime(),"Bad midichannel")
|
||||||
|
|
||||||
|
'''
|
||||||
|
MIDI Full CCs all 128 channels and data use ;fmnndd
|
||||||
|
|
||||||
|
m : midi channel 0-F (0-15)
|
||||||
|
nn : number 0-3J (0-127)
|
||||||
|
dd : data 0-3J (0-127)
|
||||||
|
'''
|
||||||
|
def FullCC(udpcc):
|
||||||
|
|
||||||
|
print()
|
||||||
|
midichannel = int(udpcc[1:2],36)
|
||||||
|
#midichannel = base36.index(udpcc[1:2].upper())
|
||||||
|
ccvr = int(udpcc[2:4],36)
|
||||||
|
ccvl = int(udpcc[4:6],36)
|
||||||
|
|
||||||
|
if midichannel < 16:
|
||||||
|
|
||||||
|
if gstt.debug > 0:
|
||||||
|
print(GetTime(),"ccvr=%d/ccvl=%d"%(ccvr,ccvl))
|
||||||
|
|
||||||
|
if gstt.oscname == "ocs2":
|
||||||
|
gstt.crtvalueOCS2[ccvr]=ccvl
|
||||||
|
else:
|
||||||
|
gstt.crtvalueMMO3[ccvr]=ccvl
|
||||||
|
|
||||||
|
for mididevice in midi3.findJamDevices(gstt.oscname):
|
||||||
|
midi3.cc(midichannel, ccvr, ccvl, mididevice)
|
||||||
|
WScom.sendWSall("/"+midi3.findJamName(mididevice, midichannel)+"/cc/"+str(ccvr)+" "+str(ccvl))
|
||||||
|
|
||||||
|
else:
|
||||||
|
print(GetTime(),"Bad midichannel")
|
||||||
|
|
169
libs/WScom.py
Normal file
169
libs/WScom.py
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# -*- mode: Python -*-
|
||||||
|
|
||||||
|
'''
|
||||||
|
WScom for jamidi v0.1b
|
||||||
|
|
||||||
|
WScom.Start(serverIP, wsPORT)
|
||||||
|
WScom.runforever()
|
||||||
|
handler : message_received(client, wserver, message)
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
import midi3
|
||||||
|
|
||||||
|
#import socket
|
||||||
|
import types, json
|
||||||
|
import _thread, time
|
||||||
|
|
||||||
|
from websocket_server import WebsocketServer
|
||||||
|
import gstt
|
||||||
|
import UDPcom, OSCom
|
||||||
|
|
||||||
|
def Start(serverIP, wsPORT):
|
||||||
|
global wserver
|
||||||
|
|
||||||
|
wserver = WebsocketServer(wsPORT,host=serverIP)
|
||||||
|
midi3.ws = wserver
|
||||||
|
|
||||||
|
wserver.set_fn_new_client(new_client)
|
||||||
|
wserver.set_fn_client_left(client_left)
|
||||||
|
wserver.set_fn_message_received(message_received)
|
||||||
|
|
||||||
|
|
||||||
|
def runforever():
|
||||||
|
wserver.run_forever()
|
||||||
|
|
||||||
|
|
||||||
|
# Called for every WS client connecting (after handshake)
|
||||||
|
def new_client(client, wserver):
|
||||||
|
|
||||||
|
|
||||||
|
print(midi3.GetTime(),"New WS client connected and was given id %d" % client['id'])
|
||||||
|
#sendWSall("/status Hello %d" % client['id'])
|
||||||
|
if gstt.current == True:
|
||||||
|
sendallcurrentccvalues("mmo3")
|
||||||
|
sendallcurrentccvalues("ocs2")
|
||||||
|
|
||||||
|
gstt.Players+=1
|
||||||
|
sendWSall("/status Hello %d" %(client['id']))
|
||||||
|
if gstt.Players > 1:
|
||||||
|
#sendWSall("/gstt.Players %d" %(Players))
|
||||||
|
sendWSall("/players (players:%d)" %(gstt.Players))
|
||||||
|
else:
|
||||||
|
sendWSall("/players (player:%d)" %(gstt.Players))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Called for every WS client disconnecting
|
||||||
|
def client_left(client, wserver):
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
print(midi3.GetTime(),"WS Client(%d) disconnected" % client['id'])
|
||||||
|
gstt.Players-=1
|
||||||
|
sendWSall("/players %d" %(gstt.Players))
|
||||||
|
except:
|
||||||
|
print("Something weird if coming from",client,"on the wire...")
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# Called for each WS received message.
|
||||||
|
def message_received(client, wserver, message):
|
||||||
|
|
||||||
|
print("")
|
||||||
|
if len(message) > 200:
|
||||||
|
message = message[:200]+'..'
|
||||||
|
|
||||||
|
wspath = message.split(" ")
|
||||||
|
if gstt.debug > 0:
|
||||||
|
print(midi3.GetTime(),"Main got from WS", client['id'], "said :", message, "splitted in an wspath :", wspath)
|
||||||
|
else:
|
||||||
|
print(midi3.GetTime(),"Main got WS Client", client['id'], "said :", message)
|
||||||
|
|
||||||
|
wscommand = wspath[0].split("/")
|
||||||
|
|
||||||
|
# gstt.debug
|
||||||
|
if gstt.debug > 0:
|
||||||
|
print("wscommand :",wscommand)
|
||||||
|
|
||||||
|
# noarg
|
||||||
|
if len(wspath) == 1:
|
||||||
|
args[0] = "noargs"
|
||||||
|
#print "noargs command"
|
||||||
|
|
||||||
|
|
||||||
|
# CC : /device/cc/2 127
|
||||||
|
elif wscommand[2] == "cc":
|
||||||
|
ccvr=int(wscommand[3]) #cc variable
|
||||||
|
ccvl=int(wspath[1]) #cc value
|
||||||
|
if gstt.debug > 0:
|
||||||
|
print("ccvr=%d/ccvl=%d"%(ccvr,ccvl))
|
||||||
|
if wscommand[1] == "ocs2":
|
||||||
|
gstt.crtvalueOCS2[ccvr]=ccvl
|
||||||
|
else:
|
||||||
|
gstt.crtvalueMMO3[ccvr]=ccvl
|
||||||
|
|
||||||
|
for mididevice in midi3.findJamDevices(wscommand[1]):
|
||||||
|
midi3.cc(gstt.Confs[wscommand[1]][0]["midichan"], ccvr, ccvl, mididevice)
|
||||||
|
|
||||||
|
|
||||||
|
# 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":
|
||||||
|
for mididevice in midi3.findJamDevices(wscommand[1]):
|
||||||
|
midi3.NoteOn(int(wspath[1]), int(wspath[2]), mididevice)
|
||||||
|
#midi3.NoteOn(int(wspath[1]), int(wspath[2]), gstt.Confs[wscommand[1]][0]["mididevice"])
|
||||||
|
|
||||||
|
|
||||||
|
# NOTEOFF /device/noteoff note
|
||||||
|
elif wscommand[2] == "noteoff":
|
||||||
|
for mididevice in midi3.findJamDevices(wscommand[1]):
|
||||||
|
midi3.NoteOff(int(wspath[1]), mididevice)
|
||||||
|
#midi3.NoteOff(int(wspath[1]), gstt.Confs[wscommand[1]][0]["mididevice"])
|
||||||
|
|
||||||
|
|
||||||
|
# Loop back : WS Client -> server -> WS Client
|
||||||
|
sendWSall(message)
|
||||||
|
|
||||||
|
# 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 send(message):
|
||||||
|
|
||||||
|
if gstt.clientmode == True:
|
||||||
|
send(message)
|
||||||
|
else:
|
||||||
|
wserver.send_message_to_all(msg = message)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def sendWSall(message):
|
||||||
|
|
||||||
|
if gstt.broadcast == True:
|
||||||
|
if gstt.debug >0:
|
||||||
|
print(midi3.GetTime(),"WS sending to all %s" % (message))
|
||||||
|
|
||||||
|
wserver.send_message_to_all(message)
|
||||||
|
|
||||||
|
# /send all current cc values
|
||||||
|
def sendallcurrentccvalues(nozoid):
|
||||||
|
|
||||||
|
if gstt.broadcast == True:
|
||||||
|
#print ""
|
||||||
|
print(midi3.GetTime(),"sending all current cc values of", nozoid)
|
||||||
|
|
||||||
|
if nozoid == "mmo3":
|
||||||
|
for ccnumber in range(0,32):
|
||||||
|
sendWSall("/mmo3/cc/"+str(ccnumber)+" "+str(gstt.crtvalueMMO3[ccnumber]))
|
||||||
|
else:
|
||||||
|
for ccnumber in range(0,32):
|
||||||
|
sendWSall("/ocs2/cc/"+str(ccnumber)+" "+str(gstt.crtvalueOCS2[ccnumber]))
|
39
libs/gstt.py
Normal file
39
libs/gstt.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# -*- mode: Python -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Jamidi states
|
||||||
|
v0.2.4b
|
||||||
|
|
||||||
|
|
||||||
|
LICENCE : CC
|
||||||
|
by Sam Neurohack
|
||||||
|
from /team/laser
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# reset = [64,64,0,32,96] # un truc comme ca pour les valeurs de reset ?
|
||||||
|
resetMMO3 = [0] * 32
|
||||||
|
resetOCS2 = [0] * 32
|
||||||
|
|
||||||
|
# record current values
|
||||||
|
crtvalueMMO3 = [0] * 32
|
||||||
|
crtvalueOCS2 = [0] * 32
|
||||||
|
|
||||||
|
# record number of loaded pages (aka client id or players)
|
||||||
|
Players=0
|
||||||
|
|
||||||
|
oscname = ""
|
||||||
|
Confs = []
|
||||||
|
|
||||||
|
debug = 0
|
||||||
|
|
||||||
|
BS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
def to_base(s, b):
|
||||||
|
res = ""
|
||||||
|
while s:
|
||||||
|
res+=BS[s%b]
|
||||||
|
s//= b
|
||||||
|
return res[::-1] or "0"
|
@ -36,6 +36,8 @@ import sys
|
|||||||
from sys import platform
|
from sys import platform
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import gstt
|
||||||
|
import WScom
|
||||||
|
|
||||||
|
|
||||||
is_py2 = sys.version[0] == '2'
|
is_py2 = sys.version[0] == '2'
|
||||||
@ -61,10 +63,8 @@ midinputsname = ["Name"] * 16
|
|||||||
midinputsqueue = [Queue() for i in range(16) ]
|
midinputsqueue = [Queue() for i in range(16) ]
|
||||||
midinputs = []
|
midinputs = []
|
||||||
|
|
||||||
debug = 0
|
|
||||||
|
|
||||||
# False = server / True = Client
|
# False = server / True = Client
|
||||||
clientmode = False
|
gstt.clientmode = False
|
||||||
|
|
||||||
#Mser = False
|
#Mser = False
|
||||||
|
|
||||||
@ -152,6 +152,7 @@ def note2midi(note_name):
|
|||||||
pitch = match.group('n').upper()
|
pitch = match.group('n').upper()
|
||||||
offset = acc_map[match.group('off')]
|
offset = acc_map[match.group('off')]
|
||||||
octave = int(match.group('oct'))
|
octave = int(match.group('oct'))
|
||||||
|
|
||||||
except:
|
except:
|
||||||
raise ValueError('Improper note format: {}'.format(note_name))
|
raise ValueError('Improper note format: {}'.format(note_name))
|
||||||
# Convert from the extrated ints to a full note number
|
# Convert from the extrated ints to a full note number
|
||||||
@ -189,17 +190,17 @@ def midi2hz(note_number):
|
|||||||
# in a 440 Hz tuning
|
# in a 440 Hz tuning
|
||||||
return 440.0*(2.0**((note_number - 69)/12.0))
|
return 440.0*(2.0**((note_number - 69)/12.0))
|
||||||
|
|
||||||
|
# /cc cc number value
|
||||||
|
def cc(midichannel, ccnumber, value, mididest):
|
||||||
|
|
||||||
|
if gstt.debug>0:
|
||||||
|
print(GetTime(),"Jamidi Sending Midi channel", midichannel, "cc", ccnumber, "value", value, "to", mididest)
|
||||||
|
|
||||||
|
MidiMsg([CONTROLLER_CHANGE+midichannel-1, ccnumber, value], mididest)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 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
|
# MIDI Startup and handling
|
||||||
@ -231,8 +232,18 @@ def MidinProcess(inqueue, portname):
|
|||||||
MidiVel = msg[2]
|
MidiVel = msg[2]
|
||||||
print(GetTime(),"NOTE ON :", MidiNote, 'velocity :', MidiVel, "Channel", MidiChannel)
|
print(GetTime(),"NOTE ON :", MidiNote, 'velocity :', MidiVel, "Channel", MidiChannel)
|
||||||
#NoteOn(msg[1],msg[2],mididest)
|
#NoteOn(msg[1],msg[2],mididest)
|
||||||
|
#NoteOn(msg[1],msg[2],mididest,MidiChannel-1)
|
||||||
|
|
||||||
|
#beware !!
|
||||||
|
if gstt.nothrough == False:
|
||||||
|
for mididevice in findJamDevices(gstt.oscname):
|
||||||
|
#NoteOn(msg[1],msg[2],"XXXX",MidiChannel-1)
|
||||||
|
if gstt.debug>0:
|
||||||
|
print(GetTime(),"mididevice/oscname:",mididevice,"/",gstt.oscname)
|
||||||
|
NoteOn(msg[1],msg[2],mididevice,MidiChannel-1)
|
||||||
|
|
||||||
print(GetTime(),"Midi in process send /"+findJamName(portname, MidiChannel)+"/noteon "+str(msg[1])+" "+str(msg[2]))
|
print(GetTime(),"Midi in process send /"+findJamName(portname, MidiChannel)+"/noteon "+str(msg[1])+" "+str(msg[2]))
|
||||||
wssend("/"+findJamName(portname, MidiChannel)+"/noteon "+str(msg[1])+" "+str(msg[2]))
|
WScom.send("/"+findJamName(portname, MidiChannel)+"/noteon "+str(msg[1])+" "+str(msg[2]))
|
||||||
|
|
||||||
'''
|
'''
|
||||||
# Sampler mode : note <63 launch snare.wav / note > 62 kick.wav
|
# Sampler mode : note <63 launch snare.wav / note > 62 kick.wav
|
||||||
@ -264,7 +275,7 @@ def MidinProcess(inqueue, portname):
|
|||||||
print(GetTime(),"NOTE OFF :", MidiNote, 'velocity :', MidiVel, "Channel", MidiChannel)
|
print(GetTime(),"NOTE OFF :", MidiNote, 'velocity :', MidiVel, "Channel", MidiChannel)
|
||||||
#NoteOff(msg[1],msg[2], mididest)
|
#NoteOff(msg[1],msg[2], mididest)
|
||||||
print(GetTime(),"Midi in process send /"+findJamName(portname, MidiChannel)+"/noteoff "+str(msg[1]))
|
print(GetTime(),"Midi in process send /"+findJamName(portname, MidiChannel)+"/noteoff "+str(msg[1]))
|
||||||
wssend("/"+findJamName(portname, MidiChannel)+"/noteoff "+str(msg[1]))
|
WScom.send("/"+findJamName(portname, MidiChannel)+"/noteoff "+str(msg[1]))
|
||||||
|
|
||||||
|
|
||||||
# # CC on all Midi Channels
|
# # CC on all Midi Channels
|
||||||
@ -274,7 +285,7 @@ def MidinProcess(inqueue, portname):
|
|||||||
#findJamName(portname, MidiChannel)
|
#findJamName(portname, MidiChannel)
|
||||||
print(GetTime(),"channel", MidiChannel, " ",findJamName(portname, MidiChannel), " CC :", msg[1], msg[2])
|
print(GetTime(),"channel", MidiChannel, " ",findJamName(portname, MidiChannel), " CC :", msg[1], msg[2])
|
||||||
print(GetTime(),"Midi in process send /"+findJamName(portname, MidiChannel)+"/cc/"+str(msg[1])+" "+str(msg[2])+" to WS")
|
print(GetTime(),"Midi in process send /"+findJamName(portname, MidiChannel)+"/cc/"+str(msg[1])+" "+str(msg[2])+" to WS")
|
||||||
wssend("/"+findJamName(portname, MidiChannel)+"/cc/"+str(msg[1])+" "+str(msg[2]))
|
WScom.send("/"+findJamName(portname, MidiChannel)+"/cc/"+str(msg[1])+" "+str(msg[2]))
|
||||||
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -282,7 +293,7 @@ def MidinProcess(inqueue, portname):
|
|||||||
if CONTROLLER_CHANGE -1 < msg[0] < 192:
|
if CONTROLLER_CHANGE -1 < msg[0] < 192:
|
||||||
print("channel 1 (MMO-3) CC :", msg[1], msg[2])
|
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")
|
print("Midi in process send /mmo3/cc/"+str(msg[1])+" "+str(msg[2])+" to WS")
|
||||||
wssend("/mmo3/cc/"+str(msg[1])+" "+str(msg[2]))
|
WScom.send("/mmo3/cc/"+str(msg[1])+" "+str(msg[2]))
|
||||||
|
|
||||||
|
|
||||||
# OCS-2 Midi CC message CHANNEL 2
|
# OCS-2 Midi CC message CHANNEL 2
|
||||||
@ -290,7 +301,7 @@ def MidinProcess(inqueue, portname):
|
|||||||
print("channel 2 (OCS-2) CC :", msg[1], msg[2])
|
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")
|
print("Midi in process send /ocs2/cc/"+str(msg[1])+" "+str(msg[2])+" to WS")
|
||||||
wssend("/ocs2/cc/"+str(msg[1])+" "+str(msg[2]))
|
WScom.send("/ocs2/cc/"+str(msg[1])+" "+str(msg[2]))
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
@ -303,19 +314,24 @@ def MidinProcess(inqueue, portname):
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
def NoteOn(note,color, mididest):
|
#def NoteOn(note, color, mididest):
|
||||||
|
#https://pypi.org/project/python-rtmidi/0.3a/
|
||||||
|
#à NOTE_ON=#90 et NOTE_OFF=#80 on ajoute le channel (0 le premier) pour envoyer effectivement sur le channel
|
||||||
|
def NoteOn(note, color, mididest, midichannel=0):
|
||||||
global MidInsNumber
|
global MidInsNumber
|
||||||
|
|
||||||
|
if gstt.debug >0:
|
||||||
|
print(GetTime(),"Sending", note, color, "to", mididest, "on channel", midichannel)
|
||||||
|
|
||||||
for port in range(MidInsNumber):
|
for port in range(MidInsNumber):
|
||||||
|
|
||||||
# To mididest
|
# To mididest
|
||||||
if midiname[port].find(mididest) == 0:
|
if midiname[port].find(mididest) == 0:
|
||||||
midiport[port].send_message([NOTE_ON, note, color])
|
midiport[port].send_message([NOTE_ON+midichannel, note, color])
|
||||||
|
|
||||||
# To All
|
# To All
|
||||||
elif mididest == "all" and midiname[port].find(mididest) != 0:
|
elif mididest == "all" and midiname[port].find(mididest) != 0:
|
||||||
midiport[port].send_message([NOTE_ON, note, color])
|
midiport[port].send_message([NOTE_ON+midichannel, note, color])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -491,8 +507,8 @@ def InConfig():
|
|||||||
print(GetTime(),"MIDIin...")
|
print(GetTime(),"MIDIin...")
|
||||||
|
|
||||||
# client mode
|
# client mode
|
||||||
if debug > 0:
|
if gstt.debug > 0:
|
||||||
if clientmode == True:
|
if gstt.clientmode == True:
|
||||||
print(GetTime(),"midi3 in client mode")
|
print(GetTime(),"midi3 in client mode")
|
||||||
else:
|
else:
|
||||||
print(GetTime(),"midi3 in server mode")
|
print(GetTime(),"midi3 in server mode")
|
||||||
@ -603,7 +619,7 @@ def MidiMsg(midimsg, mididest):
|
|||||||
for port in range(len(OutDevice)):
|
for port in range(len(OutDevice)):
|
||||||
# To mididest
|
# To mididest
|
||||||
if midiname[port].find(mididest) != -1:
|
if midiname[port].find(mididest) != -1:
|
||||||
if debug>0:
|
if gstt.debug>0:
|
||||||
print(GetTime(),"jamidi3 sending to name", midiname[port], "port", port, ":", midimsg)
|
print(GetTime(),"jamidi3 sending to name", midiname[port], "port", port, ":", midimsg)
|
||||||
midiport[port].send_message(midimsg)
|
midiport[port].send_message(midimsg)
|
||||||
desterror = 0
|
desterror = 0
|
||||||
@ -612,11 +628,11 @@ def MidiMsg(midimsg, mididest):
|
|||||||
print(GetTime(),"mididest",mididest, ": ** This midi destination doesn't exists **")
|
print(GetTime(),"mididest",mididest, ": ** This midi destination doesn't exists **")
|
||||||
|
|
||||||
# send midi msg over ws.
|
# send midi msg over ws.
|
||||||
#if clientmode == True:
|
#if gstt.clientmode == True:
|
||||||
# ws.send("/ocs2/cc/1 2")
|
# ws.send("/ocs2/cc/1 2")
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
def NoteOn(note, velocity, mididest):
|
def NoteOn(note, velocity, mididest):
|
||||||
global MidInsNumber
|
global MidInsNumber
|
||||||
|
|
||||||
@ -626,7 +642,7 @@ def NoteOn(note, velocity, mididest):
|
|||||||
# To mididest
|
# To mididest
|
||||||
if midiname[port].find(mididest) == 0:
|
if midiname[port].find(mididest) == 0:
|
||||||
midiport[port].send_message([NOTE_ON, note, velocity])
|
midiport[port].send_message([NOTE_ON, note, velocity])
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
def listdevice(number):
|
def listdevice(number):
|
||||||
@ -638,17 +654,20 @@ def listdevice(number):
|
|||||||
# return device name for given mididevice and midichannel
|
# return device name for given mididevice and midichannel
|
||||||
def findJamName(mididevice, midichan):
|
def findJamName(mididevice, midichan):
|
||||||
|
|
||||||
#print("searching", mididevice, "channel", midichan,'...')
|
|
||||||
|
|
||||||
for (k, v) in Confs.items():
|
if gstt.debug >0:
|
||||||
|
print(GetTime(),"Findjamname searching", mididevice, "channel", midichan,'...')
|
||||||
|
|
||||||
|
for (k, v) in gstt.Confs.items():
|
||||||
#print("Key: " + k)
|
#print("Key: " + k)
|
||||||
#print("Value: " + str(v))
|
#print("Value: " + str(v))
|
||||||
if v[0]["type"] == "mididevice":
|
if v[0]["type"] == "mididevice":
|
||||||
|
|
||||||
#print(v[0]["mididevice"],v[0]["midichan"], type(v[0]["midichan"]))
|
#print(k, v[0]["mididevice"],v[0]["midichan"],type(v[0]["midichan"]),v[0]["xname"], "?")
|
||||||
if (v[0]["mididevice"] == mididevice) and (v[0]["midichan"] == midichan):
|
if (v[0]["mididevice"] == mididevice) and (v[0]["midichan"] == midichan):
|
||||||
print(GetTime(),"Incoming event from", k, "xname", v[0]["xname"])
|
print(GetTime(),"Incoming event from", k, "xname", v[0]["xname"])
|
||||||
return v[0]["xname"]
|
return v[0]["xname"]
|
||||||
|
|
||||||
return "None"
|
return "None"
|
||||||
|
|
||||||
|
|
||||||
@ -656,15 +675,17 @@ def findJamName(mididevice, midichan):
|
|||||||
def findJamDevices(name):
|
def findJamDevices(name):
|
||||||
|
|
||||||
devices = []
|
devices = []
|
||||||
print (GetTime(),"searching", name)
|
if gstt.debug >0:
|
||||||
for (k, v) in Confs.items():
|
print (GetTime(),"Findjamdevice searching", name)
|
||||||
|
for (k, v) in gstt.Confs.items():
|
||||||
|
|
||||||
if v[0]["type"] == "mididevice":
|
if v[0]["type"] == "mididevice":
|
||||||
#print(k, name,v[0]["xname"])
|
#print(k, name,v[0]["xname"])
|
||||||
if v[0]["xname"] == name:
|
if v[0]["xname"] == name:
|
||||||
#print(v[0]["mididevice"])
|
#print(v[0]["mididevice"])
|
||||||
devices.append(v[0]["mididevice"])
|
devices.append(v[0]["mididevice"])
|
||||||
# print(devices)
|
if gstt.debug>0:
|
||||||
|
print(GetTime(),devices)
|
||||||
return devices
|
return devices
|
||||||
|
|
||||||
|
|
||||||
|
343
main.py
343
main.py
@ -14,6 +14,21 @@ wserver.run_forever()
|
|||||||
|
|
||||||
wserver.send_message_to_all(message)
|
wserver.send_message_to_all(message)
|
||||||
|
|
||||||
|
ORCA:
|
||||||
|
|
||||||
|
CTRL K pour rentrer une commande
|
||||||
|
|
||||||
|
CTRL K ip:127.0.0.1
|
||||||
|
CTRL K osc:8082
|
||||||
|
CTRL K cc:0
|
||||||
|
CTRL K udp:udport
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/p
|
||||||
|
Pitch bend
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@ -33,28 +48,36 @@ from rtmidi.midiconstants import (CHANNEL_PRESSURE, CONTROLLER_CHANGE, NOTE_ON,
|
|||||||
sys.path.append('libs/')
|
sys.path.append('libs/')
|
||||||
import midi3
|
import midi3
|
||||||
|
|
||||||
from websocket_server import WebsocketServer
|
|
||||||
#import socket
|
#import socket
|
||||||
import types, json
|
import types, json
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
|
import _thread, time
|
||||||
|
|
||||||
debug = 1
|
from midi3 import note2midi
|
||||||
|
from midi3 import GetTime
|
||||||
|
|
||||||
|
import OSCom
|
||||||
|
import WScom
|
||||||
|
import UDPcom
|
||||||
|
import gstt
|
||||||
|
|
||||||
|
|
||||||
print ("")
|
print ("")
|
||||||
print ("Arguments parsing if needed...")
|
print ("Arguments parsing if needed...")
|
||||||
argsparser = argparse.ArgumentParser(description="Jamidi Server v0.1b commands help mode")
|
argsparser = argparse.ArgumentParser(description="Jamidi Server v0.1b commands help mode")
|
||||||
argsparser.add_argument("-s","--servername",help="Servername: 'local', 'llstrvpn' (local by default)", type=str)
|
argsparser.add_argument("-s","--servername",help="Servername: 'local', 'llstrvpn' (local by default)", type=str)
|
||||||
argsparser.add_argument('--current',help="Send all current CC values to all new client. Default option" , dest='current', action='store_true')
|
argsparser.add_argument("-d","--device",help="midi device for incoming ORCA via UDP (mmo3 by default)", type=str)
|
||||||
argsparser.add_argument('--no-current',help="Do not send all current CC values to all new client. ", dest='current', action='store_false')
|
argsparser.add_argument('-nothrough',help="Disable the builtin midithrough from any midi IN to --device enabled by default", dest='nothrough', action='store_true')
|
||||||
argsparser.add_argument('--broadcast',help="Broadcast all incomings commands to all client. Default option" , dest='broadcast', action='store_true')
|
argsparser.set_defaults(nothrough=False)
|
||||||
argsparser.add_argument('--no-broadcast',help="Do not broadcast all incomings commands to all client", dest='broadcast', action='store_false')
|
argsparser.add_argument('-nocurrent',help="Do not send all current CC values to all new client (enabled by default)", dest='current', action='store_false')
|
||||||
argsparser.add_argument('--reset',help="Send reset values to local device a startup. Default option" , dest='reset', action='store_true')
|
|
||||||
argsparser.add_argument('--no-reset',help="Do not send reset values to local device a startup.", dest='reset', action='store_false')
|
|
||||||
argsparser.set_defaults(reset=True)
|
|
||||||
argsparser.set_defaults(current=True)
|
argsparser.set_defaults(current=True)
|
||||||
|
argsparser.add_argument('-nobroadcast',help="Do not broadcast all incomings commands to all client (enabled by default)", dest='broadcast', action='store_false')
|
||||||
argsparser.set_defaults(broadcast=True)
|
argsparser.set_defaults(broadcast=True)
|
||||||
|
argsparser.add_argument('-noreset',help="Do not broadcast all incomings commands to all client (enabled by default)", dest='reset', action='store_false')
|
||||||
|
argsparser.set_defaults(reset=True)
|
||||||
|
argsparser.add_argument('-verbose',help="Enable debug mode (disabled by default)", dest='verbose', action='store_true')
|
||||||
|
argsparser.set_defaults(verbose=False)
|
||||||
|
|
||||||
args = argsparser.parse_args()
|
args = argsparser.parse_args()
|
||||||
|
|
||||||
@ -64,41 +87,95 @@ if args.servername:
|
|||||||
else:
|
else:
|
||||||
servername = "local"
|
servername = "local"
|
||||||
|
|
||||||
|
# ORCA destination device
|
||||||
|
if args.device:
|
||||||
|
gstt.oscname = args.device
|
||||||
|
else:
|
||||||
|
gstt.oscname = "mmo3"
|
||||||
|
|
||||||
|
|
||||||
# Broadcast commands to all clients ?
|
# Broadcast commands to all clients ?
|
||||||
if args.broadcast == False:
|
if args.broadcast == False:
|
||||||
print("Broadcast disabled")
|
print("Broadcast disabled")
|
||||||
broadcast = False
|
gstt.broadcast = False
|
||||||
else:
|
else:
|
||||||
print("Broadcast enabled")
|
print("Broadcast enabled")
|
||||||
broadcast = True
|
gstt.broadcast = True
|
||||||
|
|
||||||
# Send current values to all new client ?
|
# Send current values to all new client ?
|
||||||
if args.current == False:
|
if args.current == False:
|
||||||
print("Do not send current values at startup disabled")
|
print("Do not send current values at startup disabled")
|
||||||
current = False
|
gstt.current = False
|
||||||
else:
|
else:
|
||||||
print("Current values update at startup disabled")
|
print("Current values update at startup disabled")
|
||||||
current = True
|
gstt.current = True
|
||||||
|
|
||||||
# Reset at startup ?
|
# Reset at startup ?
|
||||||
if args.reset == False:
|
if args.reset == False:
|
||||||
print("Reset at startup disabled")
|
print("Reset at startup disabled")
|
||||||
startreset = False
|
gstt.startreset = False
|
||||||
else:
|
else:
|
||||||
print("Reset at startup enabled")
|
print("Reset at startup enabled")
|
||||||
startreset = True
|
gstt.startreset = True
|
||||||
|
|
||||||
|
# Debug/verbose mode ?
|
||||||
|
if args.verbose == False:
|
||||||
|
print("Debug mode disabled")
|
||||||
|
gstt.debug = 0
|
||||||
|
else:
|
||||||
|
print("Debug mode enabled")
|
||||||
|
gstt.debug = 1
|
||||||
|
|
||||||
|
# nomidithrough mode ?
|
||||||
|
if args.nothrough == False:
|
||||||
|
print("Midi through mode")
|
||||||
|
gstt.nothrough = False
|
||||||
|
else:
|
||||||
|
print("No midi through mode")
|
||||||
|
gstt.nothrough = True
|
||||||
|
|
||||||
|
|
||||||
# reset = [64,64,0,32,96] # un truc comme ca pour les valeurs de reset ?
|
#base36 = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
|
||||||
resetMMO3 = [0] * 32
|
|
||||||
resetOCS2 = [0] * 32
|
|
||||||
|
|
||||||
# record current values
|
'''
|
||||||
crtvalueMMO3 = [0] * 32
|
base36 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z}
|
||||||
crtvalueOCS2 = [0] * 32
|
|
||||||
|
transpose =
|
||||||
|
"0": None, "1": None, "2": None, "3":, None, "4":, None, "5":, "6":, "7":, "8":, "9":, "A": "A0", "B": B0,
|
||||||
|
C ,"C0", D : "D0", "E": "E0" F G H I J K L M N
|
||||||
|
"C0" "D0" "E0" "F0" "G0" "A0" "B0" "C1" "D1" "E1" "F1" "G1"
|
||||||
|
O P Q R S T U V W X Y Z
|
||||||
|
"A1" "B1" "C2" "D2" "E2" "F2" "G2" "A2" "B2" "C3" "D3" "E3"
|
||||||
|
'''
|
||||||
|
|
||||||
|
#
|
||||||
|
# Settings from jamidi.json
|
||||||
|
#
|
||||||
|
|
||||||
|
# Load midi definitions in jamidi.json
|
||||||
|
def LoadConfs():
|
||||||
|
|
||||||
|
if os.path.exists('jamidi.json'):
|
||||||
|
f=open("jamidi.json","r")
|
||||||
|
|
||||||
|
s = f.read()
|
||||||
|
gstt.Confs = json.loads(s)
|
||||||
|
#print(GetTime(),gstt.Confs)
|
||||||
|
|
||||||
|
|
||||||
|
# return midi confname number for given type
|
||||||
|
def findConfs(confname,conftype):
|
||||||
|
|
||||||
|
#print("searching", midiconfname,'...')
|
||||||
|
position = -1
|
||||||
|
for counter in range(len(gstt.Confs[conftype])):
|
||||||
|
if confname == gstt.Confs[conftype][counter]['name']:
|
||||||
|
#print(confname, "is ", counter)
|
||||||
|
position = counter
|
||||||
|
return position
|
||||||
|
|
||||||
|
LoadConfs()
|
||||||
|
|
||||||
# record number of loaded pages (aka client id or players)
|
|
||||||
Players=0
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -117,8 +194,8 @@ def GetTime():
|
|||||||
# /cc cc number value
|
# /cc cc number value
|
||||||
def cc(midichannel, ccnumber, value, mididest):
|
def cc(midichannel, ccnumber, value, mididest):
|
||||||
|
|
||||||
if debug>0:
|
if gstt.debug>0:
|
||||||
print("Jamidi Sending Midi channel", midichannel, "cc", ccnumber, "value", value, "to", mididest)
|
print(GetTime(),"Jamidi Sending Midi channel", midichannel, "cc", ccnumber, "value", value, "to", mididest)
|
||||||
|
|
||||||
midi3.MidiMsg([CONTROLLER_CHANGE+midichannel-1, ccnumber, value], mididest)
|
midi3.MidiMsg([CONTROLLER_CHANGE+midichannel-1, ccnumber, value], mididest)
|
||||||
|
|
||||||
@ -131,173 +208,17 @@ def reset(nozoid):
|
|||||||
|
|
||||||
if nozoid == "mmo3":
|
if nozoid == "mmo3":
|
||||||
for ccnumber in range(0,32):
|
for ccnumber in range(0,32):
|
||||||
midi3.MidiMsg([CONTROLLER_CHANGE+Confs["mmo3"][0]["midichan"]-1, ccnumber, resetMMO3[ccnumber]], Confs["mmo3"][0]["mididevice"])
|
midi3.MidiMsg([CONTROLLER_CHANGE+gstt.Confs["mmo3"][0]["midichan"]-1, ccnumber, gstt.resetMMO3[ccnumber]], gstt.Confs["mmo3"][0]["mididevice"])
|
||||||
sendWSall("/mmo3/cc/"+str(ccnumber)+" "+str(resetMMO3[ccnumber]))
|
WScom.sendWSall("/mmo3/cc/"+str(ccnumber)+" "+str(gstt.resetMMO3[ccnumber]))
|
||||||
crtvalueMMO3[ccnumber]=resetMMO3[ccnumber]
|
gstt.crtvalueMMO3[ccnumber]=gstt.resetMMO3[ccnumber]
|
||||||
else:
|
else:
|
||||||
for ccnumber in range(0,32):
|
for ccnumber in range(0,32):
|
||||||
midi3.MidiMsg([CONTROLLER_CHANGE+Confs["ocs2"][0]["midichan"]-1, ccnumber, resetOCS2[ccnumber]], Confs["ocs2"][0]["mididevice"])
|
midi3.MidiMsg([CONTROLLER_CHANGE+gstt.Confs["ocs2"][0]["midichan"]-1, ccnumber, gstt.resetOCS2[ccnumber]], gstt.Confs["ocs2"][0]["mididevice"])
|
||||||
sendWSall("/ocs2/cc/"+str(ccnumber)+" "+str(resetOCS2[ccnumber]))
|
WScom.sendWSall("/ocs2/cc/"+str(ccnumber)+" "+str(gstt.resetOCS2[ccnumber]))
|
||||||
crtvalueOCS2[ccnumber]=resetOCS2[ccnumber]
|
gstt.crtvalueOCS2[ccnumber]=gstt.resetOCS2[ccnumber]
|
||||||
print("End of reset for", nozoid)
|
print(GetTime(),"End of reset for", nozoid)
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
# /send all current cc values
|
|
||||||
def sendallcurrentccvalues(nozoid):
|
|
||||||
|
|
||||||
if broadcast == True:
|
|
||||||
#print ""
|
|
||||||
print(GetTime(),"sending all current cc values of", nozoid)
|
|
||||||
|
|
||||||
if nozoid == "mmo3":
|
|
||||||
for ccnumber in range(0,32):
|
|
||||||
sendWSall("/mmo3/cc/"+str(ccnumber)+" "+str(crtvalueMMO3[ccnumber]))
|
|
||||||
else:
|
|
||||||
for ccnumber in range(0,32):
|
|
||||||
sendWSall("/ocs2/cc/"+str(ccnumber)+" "+str(crtvalueOCS2[ccnumber]))
|
|
||||||
|
|
||||||
#
|
|
||||||
# Settings from jamidi.json
|
|
||||||
#
|
|
||||||
|
|
||||||
# Load midi definitions in jamidi.json
|
|
||||||
def LoadConfs():
|
|
||||||
global Confs, nbmidiconf
|
|
||||||
|
|
||||||
if os.path.exists('jamidi.json'):
|
|
||||||
f=open("jamidi.json","r")
|
|
||||||
|
|
||||||
s = f.read()
|
|
||||||
Confs = json.loads(s)
|
|
||||||
|
|
||||||
|
|
||||||
# return midi confname number for given type
|
|
||||||
def findConfs(confname,conftype):
|
|
||||||
|
|
||||||
#print("searching", midiconfname,'...')
|
|
||||||
position = -1
|
|
||||||
for counter in range(len(Confs[conftype])):
|
|
||||||
if confname == Confs[conftype][counter]['name']:
|
|
||||||
#print(confname, "is ", counter)
|
|
||||||
position = counter
|
|
||||||
return position
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Websocket part
|
|
||||||
#
|
|
||||||
|
|
||||||
# Called for every WS client connecting (after handshake)
|
|
||||||
def new_client(client, wserver):
|
|
||||||
|
|
||||||
global Players
|
|
||||||
|
|
||||||
print(GetTime(),"New WS client connected and was given id %d" % client['id'])
|
|
||||||
#sendWSall("/status Hello %d" % client['id'])
|
|
||||||
if current == True:
|
|
||||||
sendallcurrentccvalues("mmo3")
|
|
||||||
sendallcurrentccvalues("ocs2")
|
|
||||||
|
|
||||||
Players+=1
|
|
||||||
sendWSall("/status Hello %d" %(client['id']))
|
|
||||||
if Players > 1:
|
|
||||||
#sendWSall("/players %d" %(Players))
|
|
||||||
sendWSall("/players (players:%d)" %(Players))
|
|
||||||
else:
|
|
||||||
sendWSall("/players (player:%d)" %(Players))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Called for every WS client disconnecting
|
|
||||||
def client_left(client, wserver):
|
|
||||||
|
|
||||||
global Players
|
|
||||||
|
|
||||||
try:
|
|
||||||
print(GetTime(),"WS Client(%d) disconnected" % client['id'])
|
|
||||||
Players-=1
|
|
||||||
sendWSall("/players %d" %(Players))
|
|
||||||
except:
|
|
||||||
print("Something weird if coming from",client,"on the wire...")
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
# Called for each WS received message.
|
|
||||||
def message_received(client, wserver, message):
|
|
||||||
|
|
||||||
print("")
|
|
||||||
if len(message) > 200:
|
|
||||||
message = message[:200]+'..'
|
|
||||||
|
|
||||||
oscpath = message.split(" ")
|
|
||||||
if debug > 0:
|
|
||||||
print(GetTime(),"Main got from WS", client['id'], "said :", message, "splitted in an oscpath :", oscpath)
|
|
||||||
else:
|
|
||||||
print(GetTime(),"Main got WS Client", client['id'], "said :", message)
|
|
||||||
|
|
||||||
wscommand = oscpath[0].split("/")
|
|
||||||
|
|
||||||
# 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[2] == "cc":
|
|
||||||
ccvr=int(wscommand[3]) #cc variable
|
|
||||||
ccvl=int(oscpath[1]) #cc value
|
|
||||||
if debug > 0:
|
|
||||||
print("ccvr=%d/ccvl=%d"%(ccvr,ccvl))
|
|
||||||
if wscommand[1] == "ocs2":
|
|
||||||
#cc(Confs[wscommand[1]][0]["midichan"], ccvr, ccvl, Confs[wscommand[1]][0]["mididevice"])
|
|
||||||
crtvalueOCS2[ccvr]=ccvl
|
|
||||||
else:
|
|
||||||
#cc(Confs[wscommand[1]][0]["midichan"], ccvr, ccvl, Confs[wscommand[1]][0]["mididevice"])
|
|
||||||
crtvalueMMO3[ccvr]=ccvl
|
|
||||||
|
|
||||||
for mididevice in midi3.findJamDevices(wscommand[1]):
|
|
||||||
cc(Confs[wscommand[1]][0]["midichan"], ccvr, ccvl, mididevice)
|
|
||||||
|
|
||||||
|
|
||||||
# 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":
|
|
||||||
for mididevice in midi3.findJamDevices(wscommand[1]):
|
|
||||||
midi3.NoteOn(int(oscpath[1]), int(oscpath[2]), mididevice)
|
|
||||||
#midi3.NoteOn(int(oscpath[1]), int(oscpath[2]), Confs[wscommand[1]][0]["mididevice"])
|
|
||||||
|
|
||||||
|
|
||||||
# NOTEOFF /device/noteoff note
|
|
||||||
elif wscommand[2] == "noteoff":
|
|
||||||
for mididevice in midi3.findJamDevices(wscommand[1]):
|
|
||||||
midi3.NoteOff(int(oscpath[1]), mididevice)
|
|
||||||
#midi3.NoteOff(int(oscpath[1]), Confs[wscommand[1]][0]["mididevice"])
|
|
||||||
|
|
||||||
|
|
||||||
# Loop back : WS Client -> server -> WS Client
|
|
||||||
sendWSall(message)
|
|
||||||
|
|
||||||
|
|
||||||
def sendWSall(message):
|
|
||||||
|
|
||||||
if broadcast == True:
|
|
||||||
if debug >0:
|
|
||||||
print(GetTime(),"sending to all %s" % (message))
|
|
||||||
|
|
||||||
wserver.send_message_to_all(message)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -305,45 +226,43 @@ def sendWSall(message):
|
|||||||
# Running...
|
# Running...
|
||||||
#
|
#
|
||||||
|
|
||||||
LoadConfs()
|
|
||||||
|
|
||||||
serverIP = Confs[servername][0]["IP"]
|
serverIP = gstt.Confs[servername][0]["IP"]
|
||||||
wsPORT = Confs[servername][0]["port"]
|
wsPORT = gstt.Confs[servername][0]["port"]
|
||||||
print(Confs["ocs2"][0]["mididevice"])
|
OSCPORT = gstt.Confs[servername][0]["oscport"]
|
||||||
|
UDPORT = gstt.Confs[servername][0]["udport"]
|
||||||
|
|
||||||
print("Running....")
|
print()
|
||||||
|
print(GetTime(),"Launching servers...")
|
||||||
|
print(GetTime(),"Launching OSC Server", serverIP,':', OSCPORT)
|
||||||
|
OSCom.Start(serverIP, OSCPORT)
|
||||||
|
|
||||||
# Main loop do nothing. Maybe do the webui server ?
|
print(GetTime(),"Launching WS Server", serverIP,':', wsPORT)
|
||||||
try:
|
UDPcom.Start(serverIP, UDPORT)
|
||||||
#while True:
|
|
||||||
|
|
||||||
# Websocket startup
|
print(GetTime(),"Launching UDP Server", serverIP,':', UDPORT)
|
||||||
wserver = WebsocketServer(wsPORT,host=serverIP)
|
WScom.Start(serverIP, wsPORT)
|
||||||
midi3.ws = wserver
|
|
||||||
midi3.Confs = Confs
|
|
||||||
#midi3.findJamDevices("ocs2")
|
|
||||||
|
|
||||||
print("")
|
|
||||||
print(GetTime(),"Launching Jamidi Websocket server...")
|
|
||||||
print(GetTime(),"at", serverIP, "port",wsPORT)
|
|
||||||
wserver.set_fn_new_client(new_client)
|
|
||||||
wserver.set_fn_client_left(client_left)
|
|
||||||
wserver.set_fn_message_received(message_received)
|
|
||||||
|
|
||||||
if startreset == True:
|
if gstt.startreset == True:
|
||||||
print("resetting nozoids...")
|
print(GetTime(),"resetting nozoids...")
|
||||||
reset("mmo3")
|
reset("mmo3")
|
||||||
reset("ocs2")
|
reset("ocs2")
|
||||||
|
|
||||||
|
# Main
|
||||||
|
|
||||||
#print ""
|
try:
|
||||||
print(GetTime(),"WS server running forever...")
|
|
||||||
|
|
||||||
wserver.run_forever()
|
print(GetTime(),"Jamidi running forever...")
|
||||||
|
|
||||||
|
WScom.runforever()
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
|
finally:
|
||||||
|
OSCom.Stop()
|
||||||
|
|
||||||
|
|
||||||
# Gently stop on CTRL C
|
# Gently stop on CTRL C
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user