diff options
| author | sbahling <sbahling@cagafuego.fritz.box> | 2018-10-20 23:59:28 +0200 |
|---|---|---|
| committer | sbahling <sbahling@cagafuego.fritz.box> | 2018-10-20 23:59:28 +0200 |
| commit | 6effbc283b3fa5b34bd45045c81168afa979572c (patch) | |
| tree | a57236c458c1833551b81bc94ccf8d82500b117c | |
| parent | 50ae6f1fdd4fd9e880435ff7e831f7461cb5302e (diff) | |
| download | tascam-fw-osc-6effbc283b3fa5b34bd45045c81168afa979572c.tar.gz tascam-fw-osc-6effbc283b3fa5b34bd45045c81168afa979572c.tar.xz tascam-fw-osc-6effbc283b3fa5b34bd45045c81168afa979572c.zip | |
Initial refactoring work
| -rw-r--r-- | buttons.py | 246 | ||||
| -rw-r--r-- | callback.py | 27 | ||||
| -rw-r--r-- | console.py | 202 | ||||
| -rw-r--r-- | faders.py | 90 | ||||
| -rw-r--r-- | fw-1884-buttons.py | 194 | ||||
| -rw-r--r-- | strips.py | 56 | ||||
| -rw-r--r-- | tascam-fw-osc.py | 394 |
7 files changed, 815 insertions, 394 deletions
diff --git a/buttons.py b/buttons.py new file mode 100644 index 0000000..89ae479 --- /dev/null +++ b/buttons.py @@ -0,0 +1,246 @@ +#!/usr/bin/env python3 +""" + Open Sound Control send/recieve daemon for Tascam Firewire control surface + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + :copyright: Copyright (c) 2012-2014 Scott Bahling + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program (see the file COPYING); if not, write to the + Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + :license: GPL-2.0, see COPYING for details +""" + +import re +import pyautogui +from osc import osc + + +keymap = {'CTRL': 'ctrl', + 'ALT': 'alt', + 'SHIFT': 'shift', + } + + +osc_addrs = {'STOP': '/transport_stop', + 'PLAY': '/transport_play', + 'F.FWD': '/ffwd', + 'REW': '/rewind', + 'REC': '/rec_enable_toggle', + } + +re_strip_num = re.compile('.*([1-9])') + +current_bank = 1 +more_banks_up = False +more_banks_down = False + + +class Button(): + def __init__(self, console, name): + self.name = name + self.state = 0 + self.console = None + + def press(self): + self.state = 1 + print('%s pressed' % self.name) + + def release(self): + self.state = 0 + print('%s released' % self.name) + + @property + def pressed(self): + if self.state: + return True + return False + + +class EncoderButton(Button): + def __init__(self, console, name): + super().__init__(console, name) + + def press(self): + + encoder_mode = self.console.state.get('encoder_mode', None) + print(encoder_mode) + if encoder_mode == self.name: + return + + self.state = 1 + if encoder_mode: + self.console.unit.leds.turn_off(encoder_mode) + self.console.state[encoder_mode] = 0 + self.console.unit.leds.turn_on(self.name) + self.console.state['encoder_mode'] = self.name + super().press() + + +class StripSelButton(Button): + def __init__(self, console, name, strip): + super().__init__(console, name) + self.strip = strip + self.strip.select = self + + def press(self): + + strip = self.strip + print('handle_strip_sel', strip) + if self.get('REC ENABLE', 0): + if strip.recenable: + osc.send_message('/strip/recenable', (strip.num, 0)) + else: + osc.send_message('/strip/recenable', (strip.num, 1)) + super().press() + + +class StripMuteButton(Button): + def __init__(self, console, name, strip): + super().__init__(console, name) + self.strip = strip + self.strip.mute = self + + def press(self): + + strip = self.strip + if strip.mute: + strip.mute = False + osc.send_message('/strip/mute', (strip.num, 0)) + else: + strip.mute = True + osc.send_message('/strip/mute', (strip.num, 1)) + super().press() + + +class StripSoloButton(Button): + def __init__(self, console, name, strip): + super().__init__(console, name) + self.strip = strip + self.strip.solo = self + + def press(self): + + strip = self.strip + if strip.solo: + strip.solo = False + osc.send_message('/strip/solo', (strip.num, 0)) + else: + strip.solo = True + osc.send_message('/strip/solo', (strip.num, 1)) + super().press() + + +class ArrowButton(Button): + def __init__(self, console, name): + super().__init__(console, name) + + def press(self): + key = keymap.get(self.name.lower(), self.name.lower()) + pyautogui.press(key) + + +class ModButton(Button): + def __init__(self, console, name): + super().__init__(console, name) + + def mod_button_press(self): + key = keymap.get(self.name, None) + if key is None: + return + + pyautogui.keyDown(key) + super().press() + + def release(self): + key = keymap.get(self.name, None) + if key is None: + return + + pyautogui.keyUp(key) + super().release() + + +class ComputerButton(Button): + def __init__(self, console, name): + super().__init__(console, name) + + def press(self): + osc.send_message('/set_surface', (8, 7, 19, 1, 8, 11)) + super().press() + + +class ClrSoloButton(Button): + def __init__(self, console, name): + super().__init__(console, name) + + def press(self): + osc.send_message('/cancel_all_solos', 1) + super().press() + + +class LoopButton(Button): + def __init__(self, console, name): + super().__init__(console, name) + + def press(self, *args): + if self.console.state.get('loop', 0): + print('******* loop off') + osc.send_message('/loop_toggle', 0) + else: + print('******* loop on') + osc.send_message('/loop_toggle', 1) + super().press() + + +class TransportButton(Button): + def __init__(self, console, name): + super().__init__(console, name) + + def press(self): + addr = osc_addrs.get(self.name, None) + if addr: + osc.send_message(addr, 1) + super().press() + + +class BankSwitchButton(Button): + def __init__(self, console, name, direction): + super().__init__(console, name) + self.direction = direction + + def press(self): + + direction = self.direction + print(direction, more_banks_up, more_banks_down) + if direction > 0 and more_banks_up: + print('calling /bank_up 1') + osc.send_message('/bank_up', 1) + elif direction < 0 and more_banks_down: + print('calling /bank_down 1') + osc.send_message('/bank_down', 1) + super().press() + + +class NudgeButton(Button): + def __init__(self, console, name, direction): + super().__init__(console, name) + self.direction = direction + + def nudge_press(self): + direction = self.direction + print(direction) + if direction > 0: + osc.send_message('/access_action', 'Common/nudge-next-forward') + else: + osc.send_message('/access_action', 'Common/nudge-next-backward') + super().press() diff --git a/callback.py b/callback.py new file mode 100644 index 0000000..484b668 --- /dev/null +++ b/callback.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +""" + Open Sound Control send/recieve daemon for Tascam Firewire control surface + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + :copyright: Copyright (c) 2012-2014 Scott Bahling + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program (see the file COPYING); if not, write to the + Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + :license: GPL-2.0, see COPYING for details +""" + + +class CallBack(): + def __init__(self, callback_function, **args): + self.call = callback_function + self.args = args diff --git a/console.py b/console.py new file mode 100644 index 0000000..a06c5ee --- /dev/null +++ b/console.py @@ -0,0 +1,202 @@ +#!/usr/bin/env python3 +""" + Open Sound Control send/recieve daemon for Tascam Firewire control surface + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + :copyright: Copyright (c) 2012-2014 Scott Bahling + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program (see the file COPYING); if not, write to the + Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + :license: GPL-2.0, see COPYING for details +""" + +import argparse +import string +import time +import threading +from pathlib import Path + +import strips +import fw_1884_buttons + +import gi + +gi.require_version('Hinawa', '2.0') +from gi.repository import Hinawa # noqa: E402 +from hinawa_utils.tscm.tscm_console_unit import TscmConsoleUnit # noqa: E402 + + +bits32 = '{:032b}'.format + +current_bank = 1 +more_banks_up = False +more_banks_down = False + + +def check_bitR2L(data, bit): + return bool(data & (0b1 << bit)) + + +class RunningStatusThread(): + def __init__(self, console, interval=1): + """ Constructor + :type interval: int + :param interval: Check interval, in seconds + """ + self.interval = interval + + thread = threading.Thread(target=self.run, args=(console)) + thread.daemon = True # Daemonize thread + thread.start() # Start the execution + self.callbacks = set() + self.last_status = [] + + def add_callback(self, obj): + self.callbacks.add(obj) + + def remove_callback(self, obj): + self.callbacks.remove(obj) + + def fetch_status_values(self, quadlets=None, first_bit=0, last_bit=32): + if quadlets is None: + quadlets = [i for i in range(0, 16)] + + def getvalue(bits): + # reverse the bit order before slicing so the index '0' is the LSB + # and reverse back before converting to int + return int(bits32(bits)[::-1][first_bit:last_bit][::-1], 2) + + values = [getvalue(self.last_status[q]) for q in quadlets] + + if len(values) == 1: + return values[0] + + return values + + def run(self, console): + """ Method that runs forever """ + while True: + + if not self.callbacks: + continue + + try: + self.last_status = console.unit.get_status() + except Exception: + continue # we should emit warning or error here! + + for callback in self.callbacks: + callback.call(self.fetch_status_values(**callback.args)) + + time.sleep(self.interval) + + +class Console(): + def __init__(self, card): + + fullpath = seek_snd_unit_path(card) + if fullpath: + self.unit = TscmConsoleUnit(fullpath) + else: + exit() + + self.state = {} + self.strips = strips.init_strips(self.unit) + self.buttons = fw_1884_buttons.init_buttons(self) + + self.unit.connect('control', self.handle_control) + + status_thread = RunningStatusThread(self) # noqa F841 + + def handle_bit_flags(self, index, before, after): + + changed = before ^ after + + for bit in [i for i, b in enumerate(bits32(changed)) if int(b)]: + high = check_bitR2L(after, bit) + button = self.buttons[index][int(bit)] + if button is None: + print('unhandled control bit {}:{}'.format(index, bit)) + continue + + if high: + button.release() + else: + button.press() + + def handle_control(self, index, before, after): + + print('{0:02d}: {1:08x} {2:08x}'.format(index, before, after)) + + if index in [5, 6, 7, 8, 9]: + self.handle_bit_flags(index, before, after) + return + + if index in [10, 11, 12, 13, 14, 15]: + self.handle_encoder(index, before, after) + return + + +def _check_hexadecimal(literal): + if literal.find('0x') == 0: + literal = literal[2:] + if len(literal) != 16: + return False + for character in literal: + if character not in string.hexdigits: + return False + else: + return True + + +def _seek_snd_unit_from_guid(guid): + for fullpath in Path('/dev/snd').glob('hw*'): + fullpath = str(fullpath) + try: + unit = Hinawa.SndUnit() + unit.open(fullpath) + if unit.get_property('guid') == guid: + return fullpath + except Exception as e: + pass + finally: + del unit + return None + + +def seek_snd_unit_path(card_id): + # Assume as sound card number if it's digit literal. + if card_id.isdigit(): + return '/dev/snd/hwC{0}D0'.format(card_id) + # Assume as GUID on IEEE 1394 bus if it's hexadecimal literal. + elif _check_hexadecimal(card_id): + return _seek_snd_unit_from_guid(int(card_id, base=16)) + return None + + +if __name__ == "__main__": + + parser = argparse.ArgumentParser() + parser.add_argument("--card", default="1", + help="number of the ALSA sound card") + parser.add_argument("--listen-ip", default="127.0.0.1", + help="The ip to listen on") + parser.add_argument("--listen-port", type=int, default=5005, + help="The port to listen on") + parser.add_argument("--ip", default="127.0.0.1", + help="The ip of the OSC server") + parser.add_argument("--port", type=int, default=3819, + help="The port the OSC server is listening on") + args = parser.parse_args() + + console = Console(args.card) diff --git a/faders.py b/faders.py new file mode 100644 index 0000000..ed202c5 --- /dev/null +++ b/faders.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +""" + Open Sound Control send/recieve daemon for Tascam Firewire control surface + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + :copyright: Copyright (c) 2012-2014 Scott Bahling + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program (see the file COPYING); if not, write to the + Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + :license: GPL-2.0, see COPYING for details +""" + +from buttons import Button +from osc import osc + + +class Fader(Button): + def __init__(self, console, strip): + name = 'Strip {} Fader'. format(strip.num) + super().__init__(console, name) + self.strip = strip + self.pos = 0 + self.addr = '/strip/fader' + self.console_callback = self.send_pos + + @position.setter + def position(self, pos): + self.pos = pos + self.console.unit.strips + + + @property + def position(self): + return self.pos + + def send_pos(self): + osc.send_message(self.addr, (self.strip, self.pos/1023)) + + def handle_console_status(self, pos): + if pos != self.pos: + print('{}: {}'.format(self.name, pos)) + self.pos = pos + self.send_pos() + + def press(self): + self.console.status_thread.add_callback(self) + super().press() + + def release(self): + self.console.status_thread.remove_callback(self) + super().press() + + + + +def strip_fader_handler(addr, args, ssid, pos): + unit = args[0] + strip = int(ssid) + print('fader_handler', addr, ssid, pos) + pos = pos * 1023 + if strip_states[strip].name != ' ': + unit.strips[strip].fader.set_position(pos) + strip_states[strip].fader = pos + + strips[strip].fader.set_position(pos) + + + unit = args[0] + if state: + unit.leds.rew.turn_on() + else: + unit.leds.rew.turn_off() + + + +def master_fader_handler(addr, args, pos): + unit = args[0] + print('master_fader_handler', pos) + unit.master_fader.set_position(1023 * pos) + diff --git a/fw-1884-buttons.py b/fw-1884-buttons.py new file mode 100644 index 0000000..b9486d5 --- /dev/null +++ b/fw-1884-buttons.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python3 +""" + Open Sound Control send/recieve daemon for Tascam Firewire control surface + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + :copyright: Copyright (c) 2012-2014 Scott Bahling + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program (see the file COPYING); if not, write to the + Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + :license: GPL-2.0, see COPYING for details +""" + +import buttons.py + + +def init_buttons(console): + unit = console.unit + strips = console.strips + return {5: [None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + strips[1].fader, + strips[2].fader, + strips[3].fader, + strips[4].fader, + strips[5].fader, + strips[6].fader, + strips[7].fader, + strips[8].fader, + strips[0].fader, + None, + None, + None, + None, + None, + None, + None, + ], + 6: [None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + buttons.StripSelButton(unit, 'Strip 1 Sel', strips[1]), + buttons.StripSelButton(unit, 'Strip 2 Sel', strips[2]), + buttons.StripSelButton(unit, 'Strip 3 Sel', strips[3]), + buttons.StripSelButton(unit, 'Strip 4 Sel', strips[4]), + buttons.StripSelButton(unit, 'Strip 5 Sel', strips[5]), + buttons.StripSelButton(unit, 'Strip 6 Sel', strips[6]), + buttons.StripSelButton(unit, 'Strip 7 Sel', strips[7]), + buttons.StripSelButton(unit, 'Strip 8 Sel', strips[8]), + buttons.StripSoloButton(unit, 'Strip 1 Solo', strips[1]), + buttons.StripSoloButton(unit, 'Strip 2 Solo', strips[2]), + buttons.StripSoloButton(unit, 'Strip 3 Solo', strips[3]), + buttons.StripSoloButton(unit, 'Strip 4 Solo', strips[4]), + buttons.StripSoloButton(unit, 'Strip 5 Solo', strips[5]), + buttons.StripSoloButton(unit, 'Strip 6 Solo', strips[6]), + buttons.StripSoloButton(unit, 'Strip 7 Solo', strips[7]), + buttons.StripSoloButton(unit, 'Strip 8 Solo', strips[8]), + ], + 7: [buttons.StripMuteButton(unit, 'Strip 1 Mute', strips[1]), + buttons.StripMuteButton(unit, 'Strip 2 Mute', strips[2]), + buttons.StripMuteButton(unit, 'Strip 3 Mute', strips[3]), + buttons.StripMuteButton(unit, 'Strip 4 Mute', strips[4]), + buttons.StripMuteButton(unit, 'Strip 5 Mute', strips[5]), + buttons.StripMuteButton(unit, 'Strip 6 Mute', strips[6]), + buttons.StripMuteButton(unit, 'Strip 7 Mute', strips[7]), + buttons.StripMuteButton(unit, 'Strip 8 Mute', strips[8]), + buttons.EncoderButton(unit, 'AUX5'), + buttons.EncoderButton(unit, 'AUX7'), + buttons.EncoderButton(unit, 'AUX6'), + buttons.EncoderButton(unit, 'AUX8'), + None, + None, + None, + None, + buttons.Button(unit, 'FLIP'), + buttons.EncoderButton(unit, 'AUX1'), + buttons.EncoderButton(unit, 'AUX3'), + buttons.EncoderButton(unit, 'PAN'), + buttons.EncoderButton(unit, 'AUX2'), + buttons.EncoderButton(unit, 'AUX4'), + None, + None, + buttons.Button(unit, 'Control Panel'), + buttons.Button(unit, 'F1'), + buttons.Button(unit, 'ALL SAFE'), + buttons.Button(unit, 'F5'), + buttons.Button(unit, 'CUT'), + buttons.Button(unit, 'COPY'), + buttons.ModButton(unit, 'ALT'), + buttons.ModButton(unit, 'SHIFT'), + ], + 8: [buttons.Button(unit, 'F2'), + buttons.ClrSoloButton(unit, 'CLR SOLO'), + buttons.LoopButton(unit, 'LOOP'), + buttons.Button(unit, 'DEL'), + buttons.Button(unit, 'PASTE'), + buttons.Button(unit, 'UNDO'), + buttons.ModButton(unit, 'CTRL'), + buttons.Button(unit, 'Foot Switch'), + buttons.Button(unit, 'Gain Enc A', None), + buttons.Button(unit, 'Gain Enc B', None), + buttons.Button(unit, 'Q Enc A', None), + buttons.Button(unit, 'Q Enc B', None), + None, + None, + None, + None, + buttons.Button(unit, 'Freq Enc A', None), + buttons.Button(unit, 'Freq Enc B', None), + None, + None, + None, + None, + None, + None, + None, + buttons.ComputerButton(unit, 'COMPUTER'), + None, + None, + buttons.Button(unit, 'CLOCK'), + buttons.Button(unit, 'ROUTE'), + None, + None, + ], + 9: [buttons.Button(unit, 'F7'), + buttons.Button(unit, 'F8'), + buttons.Button(unit, 'F9'), + buttons.Button(unit, 'F10'), + buttons.Button(unit, 'READ'), + buttons.Button(unit, 'WRT'), + buttons.Button(unit, 'TCH'), + buttons.Button(unit, 'LATCH'), + buttons.Button(unit, 'HIGH'), + buttons.Button(unit, 'HI-MID'), + buttons.Button(unit, 'LOW-MID'), + buttons.Button(unit, 'LOW'), + buttons.ArrowButton(unit, 'UP'), + buttons.ArrowButton(unit, 'LEFT'), + buttons.ArrowButton(unit, 'DOWN'), + buttons.ArrowButton(unit, 'RIGHT'), + buttons.Button(unit, 'REC ENABLE'), + buttons.NudgeButton(unit, 'NUDGE LEFT', -1), + buttons.NudgeButton(unit, 'NUDGE RIGHT', 1), + buttons.BankSwitchButton(unit, 'BANK LEFT', -1), + buttons.BankSwitchButton(unit, 'BANK RIGHT', 1), + buttons.Button(unit, 'LOCATE LEFT'), + buttons.Button(unit, 'LOCATE RIGHT'), + buttons.Button(unit, 'SHTL'), + buttons.Button(unit, 'SET'), + buttons.Button(unit, 'IN'), + buttons.Button(unit, 'OUT'), + buttons.TransportButton(unit, 'REW'), + buttons.TransportButton(unit, 'F.FWD'), + buttons.TransportButton(unit, 'STOP'), + buttons.TransportButton(unit, 'PLAY'), + buttons.TransportButton(unit, 'REC'), + ] + } diff --git a/strips.py b/strips.py new file mode 100644 index 0000000..da656d1 --- /dev/null +++ b/strips.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +""" + Open Sound Control send/recieve daemon for Tascam Firewire control surface + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + :copyright: Copyright (c) 2012-2014 Scott Bahling + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program (see the file COPYING); if not, write to the + Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + :license: GPL-2.0, see COPYING for details +""" + +from faders import Fader + +class Strip(): + + def __init__(self, unit, num): + self.num = 0 + self.mute = None + self.solo = None + self.select = None + self.recenable = False + self.pan = 0.5 + self.fader = Fader(unit, self) + self.name = None + + def send_pan(self, delta): + addr = '/strip/pan_stereo_position' + pan = self.pan + delta * 0.02 + if pan < 0: + pan = 0 + if pan > 1.0: + pan = 1.0 + osc.send_message(addr, (self.num, pan)) + + def recv_pan(self, pan): + print('Pan: {} {}'.format(self.num, pan)) + self.pan = pan + + +def init_strips(unit): + strips = [] + for strip_num in range(0, 9): + strips.append(Strip(unit, strip_num)) + + return strips diff --git a/tascam-fw-osc.py b/tascam-fw-osc.py index 827d399..1062041 100644 --- a/tascam-fw-osc.py +++ b/tascam-fw-osc.py @@ -59,24 +59,6 @@ current_bank = 1 more_banks_up = False more_banks_down = False -class StripState(): - - def __init__(self): - self.mute = False - self.solo = False - self.select = False - self.recenable = False - self.pan = 0.5 - self.fader_touch = False - self.fader = 0.0 - self.name = None - - -strip_states = [] -for strip in range(0, 9): - strip_states.append(StripState()) - - def check_bitR2L(data, bit): return bool(data & (0b1 << bit)) @@ -120,38 +102,6 @@ def roll_over_delta(delta, ceiling=0xffff): return delta -def handle_encoder_button(index, flags, bit, bitstate, control, *args): - if bitstate: - return - - encoder_mode = control_state.get('encoder_mode', None) - print(encoder_mode) - if encoder_mode == control: - return - - control_state[control] = 1 - if encoder_mode: - unit.leds.turn_off(encoder_mode) - control_state[encoder_mode] = 0 - unit.leds.turn_on(control) - control_state['encoder_mode'] = control - - -def send_pan(strip, delta): - addr = '/strip/pan_stereo_position' - pan = strip_states[strip].pan + delta * 0.02 - if pan < 0: - pan = 0 - if pan > 1.0: - pan = 1.0 - osc.send_message(addr, (strip, pan)) - - -def recv_pan(strip, pan): - print('Pan: {} {}'.format(strip, pan)) - strip_states[strip].pan = pan - - def handle_encoder(unit, index, flags): strip1 = (index * 2 - 19) strip2 = (index * 2 - 18) @@ -175,39 +125,6 @@ def handle_encoder(unit, index, flags): control_state[enc2] = val2 -def handle_encoder_inc(index, flags, bit, bitstate, control, encoder, sense): - on = control_state.get(control, 0) - - high = bool(bitstate) - low = not high - - print(sense, on, int(low)) - if (low and on) or (high and not on): - print('no change') - return - - if sense == 'a': - complement = control_state.get(control.replace('a', 'b')) - else: - complement = control_state.get(control.replace('b', 'a')) - - if low: - control_state[control] = 1 - if complement: - delta = 0.02 - else: - delta = -0.02 - else: - control_state[control] = 0 - if not complement: - delta = 0.02 - else: - delta = -0.02 - - if sense == 'a': - delta = delta * -1 - - def handle_eq_encoder(unit, index, flags): val1 = flags & 0xffff val2 = flags >> 0x10 @@ -241,317 +158,6 @@ def handle_eq_encoder(unit, index, flags): osc.send_message('/jog', delta2 * amount) -def handle_strip_sel(index, flags, bits, bitstate, control, strip): - if bitstate: - return - - print('handle_strip_sel', strip) - if button_state.get('REC ENABLE', 0): - if strip_states[strip].recenable: - osc.send_message('/strip/recenable', (strip, 0)) - else: - osc.send_message('/strip/recenable', (strip, 1)) - - -def handle_strip_mute(index, flags, bits, bitstate, control, strip): - high = bool(bitstate) - - # only react to button press - if high: - return - - if strip_states[strip].mute: - strip_states[strip].mute = False - osc.send_message('/strip/mute', (strip, 0)) - else: - strip_states[strip].mute = True - osc.send_message('/strip/mute', (strip, 1)) - - -def handle_strip_solo(index, flags, bits, bitstate, control, *args): - high = bool(bitstate) - - # only react to button press - if high: - return - - try: - strip = int(re_strip_num.match(control).group(1)) - except Exception as e: - raise e - - if strip_states[strip].solo: - strip_states[strip].solo = False - osc.send_message('/strip/solo', (strip, 0)) - else: - strip_states[strip].solo = True - osc.send_message('/strip/solo', (strip, 1)) - - -def handle_button(index, flags, bit, bitstatus, control, *args): - if bitstatus: - print('Button Release: %s' % control) - else: - print('Button Press: %s' % control) - - -def handle_arrow_button(index, flags, bit, bitstatus, control, *args): - if bitstatus: - return - - key = keymap.get(control.lower(), control.lower()) - pyautogui.press(key) - - -def handle_mod_button(index, flags, bit, bitstatus, control, *args): - key = keymap.get(control, None) - if key is None: - return - - if bitstatus: - pyautogui.keyUp(key) - else: - pyautogui.keyDown(key) - - -def handle_computer_button(index, flags, bit, bitstate, control, *args): - if bitstate: - return - osc.send_message('/set_surface', (8, 7, 19, 1, 8, 11)) - - -def handle_clr_solo_button(index, flags, bit, bitstate, control, *args): - if bitstate: - return - osc.send_message('/cancel_all_solos', 1) - - -def handle_loop_button(index, flags, bit, bitstate, control, *args): - if bitstate: - return - if control_state.get(control, 0): - print('******* loop on') - osc.send_message('/loop_toggle', 0) - else: - print('******* loop off') - osc.send_message('/loop_toggle', 1) - - -def handle_transport(index, flags, bit, bitstate, control, *args): - if bitstate: - return - - addr = osc_addrs.get(control, None) - if addr: - osc.send_message(addr, 1) - - -def default_handler(index, flags, bit, bitstate, control, *args): - print('no handler for %s' % control) - - -def handle_fader_touch(index, flags, bit, bitstate, control, strip): - - if not bitstate: - strip_states[strip].fader_touch = True - else: - strip_states[strip].fader_touch = False - - -def handle_bank_switch(index, flags, bit, bitstate, control, direction): - # only handle button press - if bitstate: - return - - print(direction, more_banks_up, more_banks_down) - if direction > 0 and more_banks_up: - print('calling /bank_up 1') - osc.send_message('/bank_up', 1) - elif direction < 0 and more_banks_down: - print('calling /bank_down 1') - osc.send_message('/bank_down', 1) - - -def handle_nudge(index, flags, bit, bitstate, control, direction): - # only handle button press - if bitstate: - return - - print(direction) - if direction > 0: - osc.send_message('/access_action', 'Common/nudge-next-forward') - else: - osc.send_message('/access_action', 'Common/nudge-next-backward') - - -control_flags = {5: [None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - ('Fader1 Touch', handle_fader_touch, 1), - ('Fader2 Touch', handle_fader_touch, 2), - ('Fader3 Touch', handle_fader_touch, 3), - ('Fader4 Touch', handle_fader_touch, 4), - ('Fader5 Touch', handle_fader_touch, 5), - ('Fader6 Touch', handle_fader_touch, 6), - ('Fader7 Touch', handle_fader_touch, 7), - ('Fader8 Touch', handle_fader_touch, 8), - ('Fader9 Touch', handle_fader_touch, 0), - None, - None, - None, - None, - None, - None, - None, - ], - 6: [('enc1a', None, 1, 'a'), - ('enc1b', None, 1, 'b'), - ('enc3a', None, 2, 'a'), - ('enc3b', None, 2, 'b'), - ('enc5a', None, 3, 'a'), - ('enc5b', None, 3, 'b'), - ('enc7a', None, 4, 'a'), - ('enc7b', None, 4, 'b'), - ('enc2a', None, 5, 'a'), - ('enc2b', None, 5, 'b'), - ('enc4a', None, 6, 'a'), - ('enc4b', None, 6, 'b'), - ('enc6a', None, 7, 'a'), - ('enc6b', None, 7, 'b'), - ('enc8a', None, 8, 'a'), - ('enc8b', None, 8, 'b'), - ('Strip1 SEL', handle_strip_sel, 1), - ('Strip2 SEL', handle_strip_sel, 2), - ('Strip3 SEL', handle_strip_sel, 3), - ('Strip4 SEL', handle_strip_sel, 4), - ('Strip5 SEL', handle_strip_sel, 5), - ('Strip6 SEL', handle_strip_sel, 6), - ('Strip7 SEL', handle_strip_sel, 7), - ('Strip8 SEL', handle_strip_sel, 8), - ('Strip1 SOLO', handle_strip_solo, 1), - ('Strip2 SOLO', handle_strip_solo, 2), - ('Strip3 SOLO', handle_strip_solo, 3), - ('Strip4 SOLO', handle_strip_solo, 4), - ('Strip5 SOLO', handle_strip_solo, 5), - ('Strip6 SOLO', handle_strip_solo, 6), - ('Strip7 SOLO', handle_strip_solo, 7), - ('Strip8 SOLO', handle_strip_solo, 8), - ], - 7: [('Strip1 MUTE', handle_strip_mute, 1), - ('Strip2 MUTE', handle_strip_mute, 2), - ('Strip3 MUTE', handle_strip_mute, 3), - ('Strip4 MUTE', handle_strip_mute, 4), - ('Strip5 MUTE', handle_strip_mute, 5), - ('Strip6 MUTE', handle_strip_mute, 6), - ('Strip7 MUTE', handle_strip_mute, 7), - ('Strip8 MUTE', handle_strip_mute, 8), - ('AUX5', handle_encoder_button), - ('AUX7', handle_encoder_button), - ('AUX6', handle_encoder_button), - ('AUX8', handle_encoder_button), - None, - None, - None, - None, - ('FLIP', handle_button), - ('AUX1', handle_encoder_button), - ('AUX3', handle_encoder_button), - ('PAN', handle_encoder_button), - ('AUX2', handle_encoder_button), - ('AUX4', handle_encoder_button), - None, - None, - ('Control Panel', handle_button), - ('F1', handle_button), - ('ALL SAFE', handle_button), - ('F5', handle_button), - ('CUT', handle_button), - ('COPY', handle_button), - ('ALT', handle_mod_button), - ('SHIFT', handle_mod_button), - ], - 8: [('F2', handle_button), - ('CLR SOLO', handle_clr_solo_button), - ('LOOP', handle_loop_button), - ('DEL', handle_button), - ('PASTE', handle_button), - ('UNDO', handle_button), - ('CTRL', handle_mod_button), - ('Foot Switch', handle_button), - ('Gain Enc A', None), - ('Gain Enc B', None), - ('Q Enc A', None), - ('Q Enc B', None), - None, - None, - None, - None, - ('Freq Enc A', None), - ('Freq Enc B', None), - None, - None, - None, - None, - None, - None, - None, - ('COMPUTER', handle_computer_button), - None, - None, - ('CLOCK', handle_button), - ('ROUTE', handle_button), - None, - None, - ], - 9: [('F7', handle_button), - ('F8', handle_button), - ('F9', handle_button), - ('F10', handle_button), - ('READ', handle_button), - ('WRT', handle_button), - ('TCH', handle_button), - ('LATCH', handle_button), - ('HIGH', handle_button), - ('HI-MID', handle_button), - ('LOW-MID', handle_button), - ('LOW', handle_button), - ('UP', handle_arrow_button), - ('LEFT', handle_arrow_button), - ('DOWN', handle_arrow_button), - ('RIGHT', handle_arrow_button), - ('REC ENABLE', handle_button), - ('NUDGE LEFT', handle_nudge, -1), - ('NUDGE RIGHT', handle_nudge, 1), - ('BANK LEFT', handle_bank_switch, -1), - ('BANK RIGHT', handle_bank_switch, 1), - ('LOCATE LEFT', handle_button), - ('LOCATE RIGHT', handle_button), - ('SHTL', handle_button), - ('SET', handle_button), - ('IN', handle_button), - ('OUT', handle_button), - ('REW', handle_transport), - ('F.FWD', handle_transport), - ('STOP', handle_transport), - ('PLAY', handle_transport), - ('REC', handle_transport), - ] - } - - def handle_bit_flags(unit, index, flags): for bit in range(32): high = check_bitR2L(flags, bit) |
