broadcast.py 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import socket
  2. import sys
  3. import struct
  4. import time
  5. import xml.etree.ElementTree as ET
  6. import threading
  7. PORT = 13676
  8. if len(sys.argv) > 2:
  9. factor = float(sys.argv[2])
  10. else:
  11. factor = 1
  12. print 'Factor:', factor
  13. class Packet(object):
  14. def __init__(self, cmd, *data):
  15. self.cmd = cmd
  16. self.data = data
  17. if len(data) >= 8:
  18. raise ValueError('Too many data')
  19. self.data = list(self.data) + [0] * (8-len(self.data))
  20. def __str__(self):
  21. return struct.pack('>L'+('L'*len(self.data)), self.cmd, *self.data)
  22. class CMD:
  23. KA = 0 # No important data
  24. PING = 1 # Data are echoed exactly
  25. QUIT = 2 # No important data
  26. PLAY = 3 # seconds, microseconds, frequency (Hz), amplitude (0-255)
  27. s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  28. s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
  29. clients = []
  30. s.sendto(str(Packet(CMD.PING)), ('255.255.255.255', PORT))
  31. s.settimeout(0.5)
  32. try:
  33. while True:
  34. data, src = s.recvfrom(4096)
  35. clients.append(src)
  36. except socket.timeout:
  37. pass
  38. print 'Clients:'
  39. for cl in clients:
  40. print cl
  41. if sys.argv[1] == '-t':
  42. s.sendto(str(Packet(CMD.PLAY, 0, 250000, 440, 255)), cl)
  43. time.sleep(0.25)
  44. s.sendto(str(Packet(CMD.PLAY, 0, 250000, 880, 255)), cl)
  45. if sys.argv[1] == '-q':
  46. s.sendto(str(Packet(CMD.QUIT)), cl)
  47. try:
  48. iv = ET.parse(sys.argv[1]).getroot()
  49. except IOError:
  50. print 'Bad file'
  51. exit()
  52. notestreams = iv.findall("./streams/stream[@type='ns']")
  53. class NSThread(threading.Thread):
  54. def run(self):
  55. nsq, cl = self._Thread__args
  56. for note in nsq:
  57. ttime = float(note.get('time'))
  58. pitch = int(note.get('pitch'))
  59. vel = int(note.get('vel'))
  60. dur = factor*float(note.get('dur'))
  61. while time.time() - BASETIME < factor*ttime:
  62. time.sleep(factor*ttime - (time.time() - BASETIME))
  63. s.sendto(str(Packet(CMD.PLAY, int(dur), int((dur*1000000)%1000000), int(440.0 * 2**((pitch-69)/12.0)), vel*2)), cl)
  64. time.sleep(dur)
  65. threads = []
  66. for ns in notestreams:
  67. if not clients:
  68. print 'WARNING: Out of clients!'
  69. break
  70. nsq = ns.findall('note')
  71. threads.append(NSThread(args=(nsq, clients.pop(0))))
  72. BASETIME = time.time()
  73. for thr in threads:
  74. thr.start()
  75. for thr in threads:
  76. thr.join()