Skip to content

Commit

Permalink
Docopt arguments (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
bookdude13 authored Feb 13, 2017
1 parent 1e013ad commit 3435815
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 25 deletions.
21 changes: 17 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
# midi-lightshow

```
Usage:
midils.py list [<backend>]
midils.py run <midi-input> <dmx> <config> [<backend>]
midils.py run (-d || --dry) <midi-input> <config> [<backend>]
Options:
<backend> Mido backend to use [default: 'mido.backends.portmidi']
<config> Path to output configuration file
<dmx> Path to dmx output device (/dev/ttyUSB* on Unix, COM* on Windows)
-d, --dry Dry run (output to logger)
-h --help Show this text
--version Show version
```

# Setting up (this was done on a Unix system. May be slightly different commands on Windows)
Clone the repository: `git clone [email protected]:teslaworksumn/midi-lightshow.git`
Setup submodules: `git submodule init && git submodule update`
Install dependencies (may need to be run as root/sudo): `python3 setup.py install`
If using the PortMidi backend (default), you must install PortMidi: `sudo apt install libportmidi-dev`
Run: `make run`

## Notes
-This program currently uses the path /dev/ttyUSB0 for the DMX output. This can be changed in midils/midils.py, and will soon be a command line argument.
-The machine this runs on should either have portmidi installed, or should [set up a different backend](https://mido.readthedocs.io/en/latest/backends.html) (this will require a change in midils.py as well)
-The midi input chosen is the first one found by the backend. This has worked in the past, but may act inconsistently across different machines.
-[Different mido backends] (https://mido.readthedocs.io/en/latest/backends.html) can be used
93 changes: 75 additions & 18 deletions midils/midils.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,99 @@
#!/usr/bin/env python3
import os
import mido
from docopt import docopt
from IoThread import IoThread
from mapper import Mapper
from plugins import Dmx as OutDmx
from plugins import Log as OutLog
from mapper import Mapper


help_text = """MIDI Lightshow.
Usage:
midils.py list [<backend>]
midils.py run <midi-input> <dmx> <config> [<backend>]
midils.py run (-d || --dry) <midi-input> <config> [<backend>]
Options:
<backend> Mido backend to use [default: 'mido.backends.portmidi']
<config> Path to output configuration file
<dmx> Path to dmx output device (/dev/ttyUSB* on Unix, COM* on Windows)
-d, --dry Dry run (output to logger)
-h --help Show this text
--version Show version
"""

channel_outputs = []


def main():
dmx = OutDmx()
dmx.setPort('/dev/ttyUSB0')
dmx.connect()
vixenlog = OutLog()
# DMX is 1-indexed
out_function = lambda channels: dmx.sendDMX([ch + 1 for ch in channels])
#out_function = vixenlog.send
dir_path = os.path.dirname(os.path.realpath(__file__))
config_path = dir_path + '/configs/octaves.json'
mapper = Mapper(config_path)
# Parse arguments
arguments = docopt(help_text)

backend = mido.Backend(arguments['<backend>'])

try:
# Setup midi input
backend_portmidi = mido.Backend('mido.backends.portmidi')
inputs = backend_portmidi.get_input_names()
if (arguments['list']):
inputs = backend.get_input_names()
print(inputs)
elif (arguments['run']):
input_name = arguments['<midi-input>']
mapper = get_mapper(arguments)
(out_fn, cleanup_fn) = get_run_type_functions(arguments)

run(input_name, mapper, backend, out_fn, cleanup_fn)
else:
print("How did we get here?? (docopt failed us or command not accounted for)")


# Runs midi-lightshow with a light channel mapper, a mido backend, a
# unary function to handle output, and a zero-ary function to do any necessary cleanup
def run(input_name, mapper, mido_backend, out_fn, cleanup_fn):
try:
# Start listening for midi
input_thread = IoThread(backend_portmidi, inputs[0], out_function, mapper)
input_thread = IoThread(mido_backend, input_name, out_fn, mapper)
input_thread.start()
# Wait until user exits
print("Enter 'exit' to stop the program")
while input("Command: ") != 'exit':
pass
# Cleanup
input_thread.stop()
dmx.disconnect()
cleanup_fn()
except Exception as e:
print(e)

main()

# Returns the output function and cleanup function associated with the run type,
# which is determined by the user provided arguments. Dry run uses a logger,
# normal run uses a DMX output plugin
def get_run_type_functions(arguments):
if arguments['--dry']:
vixenlog = OutLog()
out_fn = vixenlog.send
cleanup_fn = lambda: None # No cleanup needed
else:
dmx = OutDmx()
dmx_port = arguments['<dmx>']
dmx.setPort(dmx_port)
dmx.connect()
# DMX is 1-indexed
out_fn = lambda channels: dmx.sendDMX([ch + 1 for ch in channels])
cleanup_fn = dmx.disconnect

return (out_fn, cleanup_fn)


# Gets the output mapper from the user provided config file. Checks if path to said
# config file exists as well. Returns the mapper if everything worked, None if problem/not found
def get_mapper(arguments):
config_file = arguments['<config>']
dir_path = os.path.dirname(os.path.realpath(__file__))
config_path = dir_path + '/configs/' + config_file
mapper = Mapper(config_path)
return mapper


if __name__ == '__main__':
main()
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

setup(
name='midi-lightshow',
version='0.1.0',
version='0.2.0',
author='Ryan Fredlund',
author_email='[email protected]',
packages=['midils'],
url='https://github.com/bookdude13/midi-lightshow',
url='https://github.com/teslaworksumn/midi-lightshow',
license='LICENSE',
description='Interface between a midi keyboard and some dmx-controlled lights',
install_requires=['mido', 'pyserial']
install_requires=['docopt', 'mido', 'pyserial']
)

0 comments on commit 3435815

Please sign in to comment.