#!/usr/bin/env python # Ingen Command-Line Interface # Copyright 2011-2012 David Robillard # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. import os.path import socket import sys import time class Client: def __init__(self, path='/tmp/ingen.sock'): self.path = path def msgencode(self, msg): if sys.version_info[0] == 3: return bytes(msg, 'utf-8') else: return msg def send(self, msg): self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) self.sock.connect(self.path) self.sock.send(self.msgencode(msg)) response = self.sock.recv(1024) self.sock.close() if response != self.msgencode('OK'): print('Error: %s' % response) return False else: return True def put(self, path, body): return self.send(''' [] a patch:Put ; patch:subject <%s> ; patch:body [ %s ] . ''' % (path, body)) def set(self, path, body): return self.send(''' [] a patch:Set ; patch:subject <%s> ; patch:body [ %s ] . ''' % (path, body)) def connect(self, tail, head): return self.send(''' [] a patch:Put ; patch:subject <%s> ; patch:body [ a ingen:Edge ; ingen:tail <%s> ; ingen:head <%s> ; ] . ''' % (os.path.commonprefix([tail, head]), tail, head)) def disconnect(self, tail, head): return self.send(''' [] a patch:Delete ; patch:body [ a ingen:Edge ; ingen:tail <%s> ; ingen:head <%s> ; ] . ''' % (tail, head)) def delete(self, path): return self.send(''' [] a patch:Delete ; patch:subject <%s> . ''' % (path)) def print_usage(): print('''Usage: %s COMMAND [ARGUMENT]... A command line interface to an Ingen server. Commands: put PATH TURTLE_FRAGMENT set PATH TURTLE_FRAGMENT connect TAIL_PATH HEAD_PATH disconnect TAIL_PATH HEAD_PATH delete PATH Paths are UNIX-style paths with strict LV2 symbol components, e.g. /foo/bar_2. Turtle fragments are used verbatim as the body of blank nodes, the syntax is identical to the descriptions in Ingen patch files. Example: ingen_cmd put /left_in 'a lv2:InputPort ; a lv2:AudioPort' ingen_cmd put /left_out 'a lv2:OutputPort ; a lv2:AudioPort' ingen_cmd put /tone 'a ingen:Node ; ingen:prototype ' ingen_cmd put /combo 'a ingen:Node ; ingen:prototype ' ingen_cmd connect /left_in /tone/left_in ingen_cmd connect /tone/left_out /combo/left_in ingen_cmd connect /combo/left_out /left_out ingen_cmd set /tone/output 'ingen:value 0.7' ''') def abort_if_num_args_less_than(num): if len(sys.argv) < num: print_usage() sys.exit(1) abort_if_num_args_less_than(3) ingen = Client() cmd = sys.argv[1] success = 0 if cmd == 'put': abort_if_num_args_less_than(3) success = ingen.put(sys.argv[2], sys.argv[3]) elif cmd == 'set': abort_if_num_args_less_than(3) success = ingen.set(sys.argv[2], sys.argv[3]) elif cmd == 'connect': abort_if_num_args_less_than(4) success = ingen.connect(sys.argv[2], sys.argv[3]) elif cmd == 'disconnect': abort_if_num_args_less_than(4) success = ingen.disconnect(sys.argv[2], sys.argv[3]) elif cmd == 'delete': success = ingen.delete(sys.argv[2]) else: print("error: Unknown command `%s'" % cmd) print_usage() sys.exit(1) if success: sys.exit(0) else: sys.exit(1)