Jelajahi Sumber

Removed track duplication kludge from mkiv and moved to broadcast

Grissess 9 tahun lalu
induk
melakukan
368b5db51d
2 mengubah file dengan 37 tambahan dan 34 penghapusan
  1. 23 10
      broadcast.py
  2. 14 24
      mkiv.py

+ 23 - 10
broadcast.py

@@ -7,6 +7,7 @@ import threading
 import thread
 import optparse
 import random
+import itertools
 
 from packet import Packet, CMD, itos
 
@@ -33,12 +34,14 @@ parser.add_option('-r', '--route', dest='routes', action='append', help='Add a r
 parser.add_option('-v', '--verbose', dest='verbose', action='store_true', help='Be verbose; dump events and actual time (can slow down performance!)')
 parser.add_option('-W', '--wait-time', dest='wait_time', type='float', help='How long to wait for clients to initially respond (delays all broadcasts)')
 parser.add_option('-B', '--bind-addr', dest='bind_addr', help='The IP address (or IP:port) to bind to (influences the network to send to)')
+parser.add_option('--repeat', dest='repeat', action='store_true', help='Repeat the file playlist indefinitely')
+parser.add_option('-n', '--number', dest='number', type='int', help='Number of clients to use; if negative (default -1), use the product of stream count and the absolute value of this parameter')
 parser.add_option('-G', '--gui', dest='gui', default='', help='set a GUI to use')
 parser.add_option('--pg-fullscreen', dest='fullscreen', action='store_true', help='Use a full-screen video mode')
 parser.add_option('--pg-width', dest='pg_width', type='int', help='Width of the pygame window')
 parser.add_option('--pg-height', dest='pg_height', type='int', help='Width of the pygame window')
 parser.add_option('--help-routes', dest='help_routes', action='store_true', help='Show help about routing directives')
-parser.set_defaults(routes=[], test_delay=0.25, random=0.0, rand_low=80, rand_high=2000, live=None, factor=1.0, duration=1.0, volume=255, wait_time=0.25, play=[], transpose=0, seek=0.0, bind_addr='', pg_width = 0, pg_height = 0)
+parser.set_defaults(routes=[], test_delay=0.25, random=0.0, rand_low=80, rand_high=2000, live=None, factor=1.0, duration=1.0, volume=255, wait_time=0.25, play=[], transpose=0, seek=0.0, bind_addr='', pg_width = 0, pg_height = 0, number=-1)
 options, args = parser.parse_args()
 
 if options.help_routes:
@@ -302,6 +305,9 @@ if options.live or options.list_live:
                             del active_set[pitch]
                         deferred_set.clear()
 
+if options.repeat:
+    args = itertools.cycle(args)
+
 for fname in args:
     try:
         iv = ET.parse(fname).getroot()
@@ -313,9 +319,11 @@ for fname in args:
 
     notestreams = iv.findall("./streams/stream[@type='ns']")
     groups = set([ns.get('group') for ns in notestreams if 'group' in ns.keys()])
+    number = (len(notestreams) * abs(options.number) if options.number < 0 else options.number)
     print len(notestreams), 'notestreams'
     print len(clients), 'clients'
     print len(groups), 'groups'
+    print number, 'clients used (number)'
 
     class Route(object):
         def __init__(self, fattr, fvalue, group, excl=False):
@@ -461,7 +469,7 @@ for fname in args:
                     return
                 time.sleep(t)
             def run(self):
-                    nsq, cl = self._Thread__args
+                    nsq, cls = self._Thread__args
                     for note in nsq:
                             ttime = float(note.get('time'))
                             pitch = float(note.get('pitch')) + options.transpose
@@ -469,7 +477,8 @@ for fname in args:
                             dur = factor*float(note.get('dur'))
                             while time.time() - BASETIME < factor*ttime:
                                     self.wait_for(factor*ttime - (time.time() - BASETIME))
-                            s.sendto(str(Packet(CMD.PLAY, int(dur), int((dur*1000000)%1000000), int(440.0 * 2**((pitch-69)/12.0)), int(vel*2 * options.volume/255.0))), cl)
+                            for cl in cls:
+                                    s.sendto(str(Packet(CMD.PLAY, int(dur), int((dur*1000000)%1000000), int(440.0 * 2**((pitch-69)/12.0)), int(vel*2 * options.volume/255.0))), cl)
                             if options.verbose:
                                 print (time.time() - BASETIME), cl, ': PLAY', pitch, dur, vel
                             playing_notes[cl] = (pitch, vel*2)
@@ -478,24 +487,28 @@ for fname in args:
                     if options.verbose:
                         print '% 6.5f'%(time.time() - BASETIME,), cl, ': DONE'
 
-    threads = []
-    for ns in notestreams:
+    threads = {}
+    nscycle = itertools.cycle(notestreams)
+    for idx, ns in zip(xrange(number), nscycle):
         cli = routeset.Route(ns)
         if cli:
             nsq = ns.findall('note')
-            threads.append(NSThread(args=(nsq, cli)))
+            if ns in threads:
+                threads[ns]._Thread__args[1].add(cli)
+            else:
+                threads[ns] = NSThread(args=(nsq, set([cli])))
 
     if options.verbose:
         print 'Playback threads:'
-        for thr in threads:
+        for thr in threads.values():
             print thr._Thread__args[1]
 
     BASETIME = time.time() - (options.seek*factor)
     if options.seek > 0:
-        for thr in threads:
+        for thr in threads.values():
             thr.drop_missed()
-    for thr in threads:
+    for thr in threads.values():
             thr.start()
-    for thr in threads:
+    for thr in threads.values():
             thr.join()
     print fname, ': Done!'

+ 14 - 24
mkiv.py

@@ -29,12 +29,11 @@ parser.add_option('--help-conds', dest='help_conds', action='store_true', help='
 parser.add_option('-p', '--program-split', dest='tracks', action='append_const', const=PROGRAMS, help='Ensure all programs are on non-mutual streams (overrides -T presently)')
 parser.add_option('-P', '--percussion', dest='perc', help='Which percussion standard to use to automatically filter to "perc" (GM, GM2, or none)')
 parser.add_option('-f', '--fuckit', dest='fuckit', action='store_true', help='Use the Python Error Steamroller when importing MIDIs (useful for extended formats)')
-parser.add_option('-n', '--target-num', dest='repeaterNumber', type='int', help='Target count of devices')
 parser.add_option('-v', '--verbose', dest='verbose', action='store_true', help='Be verbose; show important parts about the MIDI scheduling process')
-parser.add_option('-d', '--debug', dest='debug', action='store_true', help='Debugging output; show excessive output about the MIDI scheduling process')
+parser.add_option('-d', '--debug', dest='debug', action='store_true', help='Debugging output; show excessive output about the MIDI scheduling process (please use less or write to a file)')
 parser.add_option('-D', '--deviation', dest='deviation', type='int', help='Amount (in semitones/MIDI pitch units) by which a fully deflected pitchbend modifies the base pitch (0 disables pitchbend processing)')
 parser.add_option('--tempo', dest='tempo', help='Adjust interpretation of tempo (try "f1"/"global", "f2"/"track")')
-parser.set_defaults(tracks=[], repeaterNumber=1, perc='GM', deviation=2, tempo='global')
+parser.set_defaults(tracks=[], perc='GM', deviation=2, tempo='global')
 options, args = parser.parse_args()
 if options.tempo == 'f1':
     options.tempo == 'global'
@@ -447,27 +446,18 @@ for fname in args:
 
     ivstreams = ET.SubElement(iv, 'streams')
 
-    x = 0 
-    while(x<options.repeaterNumber):
-    	for group in notegroups:
-        	for ns in group.streams:
-            		ivns = ET.SubElement(ivstreams, 'stream')
-            		ivns.set('type', 'ns')
-           		if group.name is not None:
-                		ivns.set('group', group.name)
-            		for note in ns.history:
-                		ivnote = ET.SubElement(ivns, 'note')
-                		ivnote.set('pitch', str(note.pitch))
-              			ivnote.set('vel', str(note.ev.velocity))
-        	       		ivnote.set('time', str(note.abstime))
- 	               		ivnote.set('dur', str(note.duration))
-			x+=1
-			if(x>=options.repeaterNumber and options.repeaterNumber!=1):
-				break
-		if(x>=options.repeaterNumber and options.repeaterNumber!=1):
-			break
-	if(x>=options.repeaterNumber and options.repeaterNumber!=1):
-		break
+    for group in notegroups:
+            for ns in group.streams:
+                    ivns = ET.SubElement(ivstreams, 'stream')
+                    ivns.set('type', 'ns')
+                    if group.name is not None:
+                            ivns.set('group', group.name)
+                    for note in ns.history:
+                            ivnote = ET.SubElement(ivns, 'note')
+                            ivnote.set('pitch', str(note.pitch))
+                            ivnote.set('vel', str(note.ev.velocity))
+                            ivnote.set('time', str(note.abstime))
+                            ivnote.set('dur', str(note.duration))
 
     ivtext = ET.SubElement(ivstreams, 'stream', type='text')
     for tev in textstream: