simplemidi_wraper.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #! /usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. """
  4. SPDX-License-Identifier: GPL-2.0-only
  5. (c) 2012 micha@librelight.de
  6. """
  7. # file descriptor on linux /dev/midi1
  8. import sys
  9. import os
  10. #import fcntl
  11. import _thread as thread
  12. import time
  13. import copy
  14. def list_device(filter="APC_MINI"):
  15. dpath = "/dev/snd/"
  16. filter = "APC_MINI"
  17. out = []
  18. for i in os.listdir(dpath):
  19. if i.startswith("controlC"):
  20. #print(i)
  21. cmd = "udevadm info {}/{}".format(dpath,i)
  22. #print("midi device_info",cmd)
  23. r=os.popen(cmd)
  24. lines = r.readlines()
  25. ok = 0
  26. for j in lines:
  27. if filter in j:
  28. ok = 1
  29. if ok:
  30. out.append(i)
  31. for j in lines:
  32. j=j.strip()
  33. print("-",j)
  34. return out
  35. class simplemidi(object):
  36. def __init__(self,device="/dev/midi1"):
  37. self.__lock = thread.allocate_lock()
  38. self.__mode = ""
  39. #self.__lock.acquire()
  40. #self.__lock.release()
  41. self.__data = ""
  42. self.__name = device
  43. self.__open()
  44. def __close(self):
  45. os.close( self.__midi )
  46. def __open(self):
  47. try:
  48. option = os.O_RDWR | os.O_NONBLOCK # os.O_RDONLY | os.O_NONBLOCK
  49. self.__midi = os.open( self.__name, option)
  50. self.__mode = "a"
  51. except OSError as e:
  52. print("File", self.__name, "ERR: {0} ".format(e.args) )
  53. try:
  54. self.__mode = "rw"
  55. option = os.O_RDONLY | os.O_NONBLOCK
  56. self.__midi = os.open( self.__name, option)
  57. print("DEVICE MODE:",self.__mode)
  58. except OSError as e:
  59. print("File", self.__name, "ERR: {0} ".format(e.args) )
  60. input()
  61. sys.exit()
  62. print("DEVICE MODE:",self.__mode)
  63. def init(self):
  64. #placeholder pygame
  65. pass
  66. def get_device_info(self,nr):
  67. if nr == 1:
  68. return "simplemidi", self.__device
  69. else:
  70. return None
  71. def write_delayed(self,data):
  72. #import thread
  73. thread.start_new_thread(self._write_delayed,([data,0.01],)) #midi writeloop
  74. thread.start_new_thread(self._write_delayed,([data,0.1],)) #midi writeloop
  75. thread.start_new_thread(self._write_delayed,([data,1],)) #midi writeloop
  76. def _write_delayed(self,data):
  77. time.sleep(data[1])
  78. self.write(data[0])
  79. def write(self,data):
  80. self.__lock.acquire()
  81. # change midi file to write mode
  82. if self.__mode == "rw":
  83. os.close(self.__midi)
  84. option = os.O_WRONLY | os.O_NONBLOCK
  85. self.__midi = os.open( self.__name, option)
  86. if len(data) == 3:
  87. msg = ""
  88. try:
  89. msg = chr(int(data[0])) + chr(int(data[1])) + chr(int(data[2]) )
  90. #if data[0] != 191:
  91. # print(data#[msg])
  92. os.write(self.__midi, bytes(msg,"utf-8") )
  93. except Exception as e:# SyntaxError:print("midi err",[msg,data ])
  94. print("midi-single-write:", e, data)
  95. #self.__close() #STOPPING MIDI ...
  96. #self.__open()
  97. elif len(data) > 3:
  98. #print("multi sending---------------------------")
  99. for i in data:
  100. if len(i) == 3:
  101. msg = ""
  102. try:
  103. msg = chr(int(i[0])) + chr(int(i[1])) + chr(int(i[2]))
  104. print([msg])
  105. os.write(self.__midi, msg )
  106. except Exception as e:
  107. pass
  108. print("midi-multi-write:", e, data)
  109. # change midi file to read mode
  110. if self.__mode == "rw":
  111. os.close(self.__midi)
  112. option = os.O_RDONLY | os.O_NONBLOCK
  113. self.__midi = os.open( self.__name, option)
  114. self.__lock.release()
  115. def read(self,count=3):
  116. self.__lock.acquire()
  117. data = copy.deepcopy(self.__data)
  118. self.__lock.release()
  119. return data
  120. def poll(self,sysex=0):
  121. self.__lock.acquire()
  122. try:
  123. if sysex:
  124. self.__data = os.read(self.__midi, 1) #read abort if no data to read
  125. else:
  126. inp = os.read(self.__midi, 3) #read abort if no data to read
  127. try:
  128. #self.__data = [ ord( inp[0] ) ,ord( inp[1] ), ord( inp[2] ) ]
  129. self.__data = [ inp[0] , inp[1] , inp[2] ]
  130. except KeyError as e:
  131. print("File", self.__name, "ERR: {0} ".format(e.args) ,[inp])
  132. except IndexError as e:
  133. print("File", self.__name, "ERR: {0} ".format(e.args) ,[inp])
  134. self.__lock.release()
  135. return 1
  136. except OSError:
  137. time.sleep(0.01) # CPU STRESSLESS
  138. self.__lock.release()
  139. return 0