Extensions:2.6/Py/Scripts/System/HID Mapper
< Extensions:2.6 | Py | Scripts | System
UI location | View Text Editor > Templates > HID Mapping | ||
---|---|---|---|
Usage | Create a HID Mapping script similar to the provided template and run it. Then you can control blender with your MIDI device like specified in your mapping. | ||
Version | 0.2 (2012-06-06) | Author(s) | David Gnedt, Manuel Steiner, Christian Voglhuber |
Blender | >= 2.61 (except 2.63/2.63a), not:2.79 | License | GPL |
Category | System | Distribution | Extern |
Note(s) | Doesn't run with Blender 2.63/2.63a because of broken multiprocessing module. Also doesn't run in 2.79 and later (releases 2.64-2.78 not tested). |
File name | system_hid_mapper.py |
---|---|
Current version download | https://developer.blender.org/F20307 |
Python modules | atexit, functools, inspect, threading, multiprocessing, subprocess |
External Python Modules or dependencies | amidi executable (can be found in alsa-utils package) |
Warning | Currently only tested on Linux with ALSA |
---|
Sample mapping
This mapping is also provided within Blender under Text Editor > Templates > HID Mapping.
# Functions:
#
# reset_mapper()
#
#
# Constructors/Factories:
#
# AMidiSubsystem.create(device=<Device>, name=<Device Name>, debug=<True/False*>)
# MidiMessageType(status=<Status>, control=<Control>)
#
#
# Mapping class decorators:
#
# register_mapping(<subsystem>)
#
#
# Mapping method decorators:
#
# map_message(<MessageType>)
# switch_pressed(value=<Pressed Value/0x7F*>)
# switch_released(value=<Released Value/0x00*>)
# relative_value(max=<Max Value/0x80*>, break=<Break Point Value/0x40*>)
# merge(type=<MergeType.LAST*/MergeType.SUM>)
#
#
# MIDI message methods:
#
# msg.get_status()
# msg.get_control()
# msg.get_value()
#
import bpy
from system_hid_mapper import *
reset_mapper()
@register_mapping(AMidiSubsystem.create(name='TotalTrack Control MIDI 1', debug=True))
class VSEMapping(object):
@map_message(MidiMessageType(status=144, control=67)) # play left
@switch_pressed()
def play(self, msg):
''' play '''
bpy.ops.screen.animation_play()
@map_message(MidiMessageType(status=144, control=51)) # pause left
@switch_pressed()
def pause(self, msg):
''' pause '''
bpy.ops.screen.animation_cancel(restore_frame=False)
def seek(self, value):
''' move current frame '''
bpy.context.scene.frame_current = bpy.context.scene.frame_current + value
@map_message(MidiMessageType(status=144, control=73)) # loop in left
@switch_pressed()
def seek_prev(self, msg):
''' move to prev frame '''
self.seek(self, -1)
@map_message(MidiMessageType(status=144, control=74)) # loop out left
@switch_pressed()
def seek_next(self, msg):
''' move to next frame '''
self.seek(self, 1)
@map_message(MidiMessageType(status=176, control=25)) # jog left
@relative_value()
@merge(type=MergeType.SUM)
def seek_jog(self, msg):
''' move current frame '''
self.seek(self, msg.get_value())
@map_message(MidiMessageType(status=144, control=77)) # loop in right
@switch_pressed()
def jump_keyframe_prev(self, msg):
''' jump to prev keyframe '''
# requires Jump to Cut Addon
bpy.ops.screen.keyframe_jump(next=False)
@map_message(MidiMessageType(status=144, control=78)) # loop out right
@switch_pressed()
def jump_keyframe_next(self, msg):
''' jump to next keyframe '''
# requires Jump to Cut Addon
bpy.ops.screen.keyframe_jump()
@map_message(MidiMessageType(status=144, control=75)) # load track left
@switch_pressed()
def strip_toggle_mute(self, msg):
''' toggle mute of selected clip '''
sqe = bpy.context.scene.sequence_editor
if sqe is not None and sqe.active_strip is not None:
sqe.active_strip.mute = not sqe.active_strip.mute
@map_message(MidiMessageType(status=176, control=8)) # volume left
@merge(type=MergeType.LAST)
def strip_volume_keyframe_insert(self, msg):
''' set key-framed volume of selected sound clip '''
sqe = bpy.context.scene.sequence_editor
if (sqe is not None and sqe.active_strip is not None and
sqe.active_strip.type == 'SOUND'):
sqe.active_strip.volume = msg.get_value() / 127.0
sqe.active_strip.keyframe_insert(data_path='volume')