00001
00002 import pygame
00003 import pygame.midi
00004 import select
00005 import sys
00006 import yaml
00007 import rospy
00008 import roslib
00009 import time
00010 import re
00011 from optparse import OptionParser
00012
00013 roslib.load_manifest('jsk_teleop_joy')
00014 from jsk_teleop_joy.midi_util import MIDICommand, MIDIParse
00015
00016 class MIDIWriteError(Exception):
00017 pass
00018
00019 def parseRangedNumber(string):
00020 """
00021 string = 0-9 or [number-number] and this returns list of the numbers
00022 """
00023 try:
00024 val = int(string)
00025 return [val]
00026 except ValueError:
00027 if string.startswith("[") and string.endswith("]"):
00028
00029 r = re.compile("\[([0-9]+)-([0-9]+)\]")
00030 m = r.search(string)
00031 if m:
00032 first_number = m.group(1)
00033 last_number = m.group(2)
00034 return range(int(first_number), int(last_number) + 1)
00035 else:
00036 raise MIDIWriteError("failed to parse string: %s" % (string))
00037 else:
00038 raise MIDIWriteError("failed to parse string: %s" % (string))
00039
00040
00041 def main():
00042
00043 all_midi_commands = ""
00044 for c in MIDICommand.allCommands():
00045 midi_command_str = "%s (%d)" % (MIDICommand.toStr(c), c)
00046 if len(all_midi_commands) > 0:
00047 all_midi_commands = "%s, %s (%d)" % (all_midi_commands, MIDICommand.toStr(c),
00048 c)
00049 else:
00050 all_midi_commands = midi_command_str
00051 parser = OptionParser()
00052 parser.add_option("--device_index", "-d", help="device index", type="int")
00053 parser.add_option("--midi_command", "-m",
00054 help="midi command: candidates are: " + all_midi_commands)
00055 parser.add_option("--channel", "-c", help="channel. You can specify the number in 0-9 or [from-to] format", default="0")
00056 parser.add_option("--param1", "-p", help="param1. You can specify the number in 0-9 or [from-to] format")
00057 parser.add_option("--param2", "-P", help="param2. You can specify the number in 0-9 or [from-to] format")
00058 parser.add_option("--interval", "-i", help="interval between each command", default=0.1, type="float")
00059 parser.add_option("--write", "-w", help="insert this output configuration into the configuration yaml")
00060 parser.add_option("--use-param1", help="this option is only available with -w option. It specifies to use parameter1 for the intensity", action="store_true")
00061 parser.add_option("--verbose", "-v", help="verbose", action="store_true")
00062 (options, args) = parser.parse_args()
00063
00064
00065 if options.device_index == None:
00066 raise MIDIWriteError("You need to specify --device_index option")
00067 if options.midi_command == None:
00068 raise MIDIWriteError("You need to specify --midi_command option")
00069 if not options.write:
00070 if options.param1 == None:
00071 raise MIDIWriteError("You need to specify --param1 option")
00072 if options.param2 == None:
00073 raise MIDIWriteError("You need to specify --param2 option")
00074 else:
00075 pass
00076
00077
00078 midi_command = None
00079 try:
00080 midi_command = int(options.midi_command)
00081 except ValueError:
00082
00083 for candidate in MIDICommand.allCommands():
00084 if MIDICommand.toStr(candidate).lower() == options.midi_command.lower():
00085 midi_command = candidate
00086
00087 if midi_command == None:
00088 raise MIDIWriteError("Unknown midi command: %s" % (options.midi_command))
00089
00090
00091 pygame.midi.init()
00092 controller = pygame.midi.Output(options.device_index)
00093 if not options.write:
00094 for channel in parseRangedNumber(options.channel):
00095 midi_command_w_channel = midi_command | channel
00096 for param1 in parseRangedNumber(options.param1):
00097 for param2 in parseRangedNumber(options.param2):
00098 if options.verbose:
00099 print "Writing [%d, %d, %d] ([0x%X, 0x%X, 0x%X])" % (midi_command_w_channel, param1, param2,
00100 midi_command_w_channel, param1, param2)
00101 controller.write_short(midi_command_w_channel, param1, param2)
00102 rospy.sleep(options.interval)
00103 else:
00104
00105
00106
00107 with open(options.write, "r+") as f:
00108 config = yaml.load(f)
00109 if config.has_key("output"):
00110 output = config["output"]
00111 else:
00112 output = []
00113 for channel in parseRangedNumber(options.channel):
00114 if options.use_param1:
00115 configuration = (midi_command, channel, True)
00116 if configuration not in output:
00117 output.append(configuration)
00118 else:
00119 for param1 in parseRangedNumber(options.param1):
00120 configuration = (midi_command, channel, False, param1)
00121 if configuration not in output:
00122 output.append(configuration)
00123 print configuration
00124 config["output"] = output
00125 f.write(yaml.dump(config))
00126 f.close()
00127 if __name__ == "__main__":
00128 main()