summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsbahling <sbahling@mudgum.net>2018-10-21 15:10:29 +0200
committersbahling <sbahling@mudgum.net>2018-10-21 15:10:29 +0200
commitdda9a4c0fd3d6bbecab0616254ace479b5d4d233 (patch)
tree17741b579a434ee71cf6e510cce2bf99ffa869f3
parent6effbc283b3fa5b34bd45045c81168afa979572c (diff)
downloadtascam-fw-osc-dda9a4c0fd3d6bbecab0616254ace479b5d4d233.tar.gz
tascam-fw-osc-dda9a4c0fd3d6bbecab0616254ace479b5d4d233.tar.xz
tascam-fw-osc-dda9a4c0fd3d6bbecab0616254ace479b5d4d233.zip
continued refactoring
-rw-r--r--buttons.py40
-rw-r--r--console.py175
-rw-r--r--faders.py60
-rw-r--r--fw_1884_buttons.py (renamed from fw-1884-buttons.py)14
-rw-r--r--osc.py60
-rw-r--r--strips.py88
6 files changed, 328 insertions, 109 deletions
diff --git a/buttons.py b/buttons.py
index 89ae479..5f1ffbe 100644
--- a/buttons.py
+++ b/buttons.py
@@ -22,7 +22,7 @@
import re
import pyautogui
-from osc import osc
+import osc
keymap = {'CTRL': 'ctrl',
@@ -90,7 +90,7 @@ class StripSelButton(Button):
def __init__(self, console, name, strip):
super().__init__(console, name)
self.strip = strip
- self.strip.select = self
+ self.strip.select_button = self
def press(self):
@@ -98,9 +98,9 @@ class StripSelButton(Button):
print('handle_strip_sel', strip)
if self.get('REC ENABLE', 0):
if strip.recenable:
- osc.send_message('/strip/recenable', (strip.num, 0))
+ osc.client.sent_message('/strip/recenable', (strip.num, 0))
else:
- osc.send_message('/strip/recenable', (strip.num, 1))
+ osc.client.sent_message('/strip/recenable', (strip.num, 1))
super().press()
@@ -108,17 +108,17 @@ class StripMuteButton(Button):
def __init__(self, console, name, strip):
super().__init__(console, name)
self.strip = strip
- self.strip.mute = self
+ self.strip.mute_button = self
def press(self):
strip = self.strip
if strip.mute:
strip.mute = False
- osc.send_message('/strip/mute', (strip.num, 0))
+ osc.client.sent_message('/strip/mute', (strip.num, 0))
else:
strip.mute = True
- osc.send_message('/strip/mute', (strip.num, 1))
+ osc.client.sent_message('/strip/mute', (strip.num, 1))
super().press()
@@ -126,17 +126,17 @@ class StripSoloButton(Button):
def __init__(self, console, name, strip):
super().__init__(console, name)
self.strip = strip
- self.strip.solo = self
+ self.strip.solo_button = self
def press(self):
strip = self.strip
if strip.solo:
strip.solo = False
- osc.send_message('/strip/solo', (strip.num, 0))
+ osc.client.sent_message('/strip/solo', (strip.num, 0))
else:
strip.solo = True
- osc.send_message('/strip/solo', (strip.num, 1))
+ osc.client.sent_message('/strip/solo', (strip.num, 1))
super().press()
@@ -175,7 +175,7 @@ class ComputerButton(Button):
super().__init__(console, name)
def press(self):
- osc.send_message('/set_surface', (8, 7, 19, 1, 8, 11))
+ osc.client.sent_message('/set_surface', (8, 7, 19, 1, 8, 11))
super().press()
@@ -184,7 +184,7 @@ class ClrSoloButton(Button):
super().__init__(console, name)
def press(self):
- osc.send_message('/cancel_all_solos', 1)
+ osc.client.sent_message('/cancel_all_solos', 1)
super().press()
@@ -195,10 +195,10 @@ class LoopButton(Button):
def press(self, *args):
if self.console.state.get('loop', 0):
print('******* loop off')
- osc.send_message('/loop_toggle', 0)
+ osc.client.sent_message('/loop_toggle', 0)
else:
print('******* loop on')
- osc.send_message('/loop_toggle', 1)
+ osc.client.sent_message('/loop_toggle', 1)
super().press()
@@ -209,7 +209,7 @@ class TransportButton(Button):
def press(self):
addr = osc_addrs.get(self.name, None)
if addr:
- osc.send_message(addr, 1)
+ osc.client.sent_message(addr, 1)
super().press()
@@ -224,10 +224,10 @@ class BankSwitchButton(Button):
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)
+ osc.client.sent_message('/bank_up', 1)
elif direction < 0 and more_banks_down:
print('calling /bank_down 1')
- osc.send_message('/bank_down', 1)
+ osc.client.sent_message('/bank_down', 1)
super().press()
@@ -240,7 +240,9 @@ class NudgeButton(Button):
direction = self.direction
print(direction)
if direction > 0:
- osc.send_message('/access_action', 'Common/nudge-next-forward')
+ osc.client.sent_message('/access_action',
+ 'Common/nudge-next-forward')
else:
- osc.send_message('/access_action', 'Common/nudge-next-backward')
+ osc.client.sent_message('/access_action',
+ 'Common/nudge-next-backward')
super().press()
diff --git a/console.py b/console.py
index a06c5ee..c7f1d2c 100644
--- a/console.py
+++ b/console.py
@@ -26,6 +26,7 @@ import time
import threading
from pathlib import Path
+import osc
import strips
import fw_1884_buttons
@@ -38,13 +39,17 @@ 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
+class ConsoleStatus():
+ def __init__(self, quadlets):
+ self.quadlets = quadlets
-def check_bitR2L(data, bit):
- return bool(data & (0b1 << bit))
+ def field(self, quadlet, first_bit=0, last_bit=32):
+ bits = self.quadlets[quadlet]
+
+ # 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)
class RunningStatusThread():
@@ -53,13 +58,14 @@ class RunningStatusThread():
:type interval: int
:param interval: Check interval, in seconds
"""
+ self.console = console
self.interval = interval
+ self.callbacks = set()
+ self.last_status = []
- thread = threading.Thread(target=self.run, args=(console))
+ thread = threading.Thread(target=self.run)
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)
@@ -67,36 +73,14 @@ class RunningStatusThread():
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):
+ def run(self):
""" 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))
+ for obj in self.callbacks:
+ value = self.console.status.field(obj.status_quadlet,
+ **obj.status_bits,
+ )
+ obj.status_callback(value)
time.sleep(self.interval)
@@ -111,19 +95,29 @@ class Console():
exit()
self.state = {}
- self.strips = strips.init_strips(self.unit)
+ self.current_bank = 1
+ self.more_banks_up = False
+ self.more_banks_down = False
+ self.strips = strips.init_strips(self)
self.buttons = fw_1884_buttons.init_buttons(self)
self.unit.connect('control', self.handle_control)
status_thread = RunningStatusThread(self) # noqa F841
+ @property
+ def status(self):
+ try:
+ return ConsoleStatus(self.unit.get_status())
+ except Exception as e:
+ raise e
+
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)
+ high = bool(after & (0b1 << bit))
button = self.buttons[index][int(bit)]
if button is None:
print('unhandled control bit {}:{}'.format(index, bit))
@@ -146,6 +140,106 @@ class Console():
self.handle_encoder(index, before, after)
return
+ def strip_fader_handler(self, addr, args, ssid, pos):
+ print('fader_handler', addr, ssid, pos)
+ strip = self.strips(int(ssid))
+ if strip.name == ' ':
+ return
+ pos = pos * 1023
+ strip.fader.position = pos
+
+ def master_fader_handler(self, addr, args, pos):
+ print('master_fader_handler', pos)
+ self.strips[0].fader.position(1023 * pos)
+
+ def default_handler(self, addr, *args):
+ print(addr, args)
+
+ def strip_mute_handler(self, addr, args, ssid, state):
+ strip = self.strips(int(ssid))
+ print('mute_handler', strip, state)
+ if strip.name == ' ':
+ return
+ if state:
+ strip.mute = True
+ else:
+ strip.mute = False
+
+ def strip_solo_handler(self, addr, args, ssid, state):
+ strip = self.strips(int(ssid))
+ print('solo_handler', strip, state)
+ if strip.name == ' ':
+ return
+ if state:
+ strip.solo = True
+ else:
+ strip.solo = False
+
+ def strip_recenable_handler(self, addr, args, ssid, state):
+ strip = self.strips(int(ssid))
+ print('recenable_handler', strip, state)
+ if strip.name == ' ':
+ return
+ if state:
+ strip.recenable = True
+ else:
+ strip.recenable = False
+
+ def loop_toggle_handler(self, addr, state):
+ print(addr, state)
+ if state:
+ self.state['LOOP'] = 1
+ self.unit.leds.loop.turn_on()
+ else:
+ self.state['LOOP'] = 0
+ self.unit.leds.loop.turn_off()
+
+ def transport_stop_handler(self, addr, args, state):
+ print(addr, args, state)
+ if state:
+ self.unit.leds.stop.turn_on()
+ else:
+ self.unit.leds.stop.turn_off()
+
+ def transport_play_handler(self, addr, args, state):
+ print(addr, args, state)
+ if state:
+ self.unit.leds.play.turn_on()
+ else:
+ self.unit.leds.play.turn_off()
+
+ def ffwd_handler(self, addr, args, state):
+ if state:
+ self.unit.leds.f_fwd.turn_on()
+ else:
+ self.unit.leds.f_fwd.turn_off()
+
+ def rewind_handler(self, addr, args, state):
+ if state:
+ self.unit.leds.rew.turn_on()
+ else:
+ self.unit.leds.rew.turn_off()
+
+ def rec_enable_toggle_handler(self, addr, args, state):
+ if state:
+ self.unit.leds.rec.turn_on()
+ else:
+ self.unit.leds.rec.turn_off()
+
+ def pan_stereo_position_handler(self, addr, pos, pan):
+ self.strips[pos].recv_pan(pan)
+
+ def strip_name_handler(self, addr, ssid, name):
+ self.strips[int(ssid)].name = name
+
+ def bank_up_handler(self, addr, more_up):
+ print(addr, more_up)
+ self.more_banks_up = bool(more_up)
+
+ def bank_down_handler(self, addr, more_down):
+ print(addr, more_down)
+ self.more_banks_down = bool(more_down)
+
def _check_hexadecimal(literal):
if literal.find('0x') == 0:
@@ -200,3 +294,8 @@ if __name__ == "__main__":
args = parser.parse_args()
console = Console(args.card)
+ osc.init_client(args.ip, args.port)
+ osc.init_server(args.listen_ip, args.listen_port, console)
+
+ print("Serving on {}".format(osc.server.server_address))
+ osc.server.serve_forever()
diff --git a/faders.py b/faders.py
index ed202c5..5d5fdde 100644
--- a/faders.py
+++ b/faders.py
@@ -21,7 +21,19 @@
"""
from buttons import Button
-from osc import osc
+import osc
+
+status_quadlets = (4, 0, 0, 1, 1, 2, 2, 3, 3)
+status_bits = ((1, 16),
+ (1, 16),
+ (17, 32),
+ (1, 16),
+ (17, 32),
+ (1, 16),
+ (17, 32),
+ (1, 16),
+ (17, 32),
+ )
class Fader(Button):
@@ -31,20 +43,21 @@ class Fader(Button):
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
-
+ self.status_quadlet = status_quadlets[self.strip.num]
+ self.status_bits = status_bits[self.strip.num]
+ self.status_callback = self.send_pos
@property
def position(self):
return self.pos
+ @position.setter
+ def position(self, pos):
+ self.pos = pos
+ self.console.unit.strips[self.strip.num].set_position(pos)
+
def send_pos(self):
- osc.send_message(self.addr, (self.strip, self.pos/1023))
+ osc.client.sent_message(self.addr, (self.strip, self.pos/1023))
def handle_console_status(self, pos):
if pos != self.pos:
@@ -59,32 +72,3 @@ class Fader(Button):
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
index b9486d5..e1ed548 100644
--- a/fw-1884-buttons.py
+++ b/fw_1884_buttons.py
@@ -20,7 +20,7 @@
:license: GPL-2.0, see COPYING for details
"""
-import buttons.py
+import buttons
def init_buttons(console):
@@ -133,16 +133,16 @@ def init_buttons(console):
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),
+ buttons.Button(unit, 'Gain Enc A'),
+ buttons.Button(unit, 'Gain Enc B'),
+ buttons.Button(unit, 'Q Enc A'),
+ buttons.Button(unit, 'Q Enc B'),
None,
None,
None,
None,
- buttons.Button(unit, 'Freq Enc A', None),
- buttons.Button(unit, 'Freq Enc B', None),
+ buttons.Button(unit, 'Freq Enc A'),
+ buttons.Button(unit, 'Freq Enc B'),
None,
None,
None,
diff --git a/osc.py b/osc.py
new file mode 100644
index 0000000..e0957a7
--- /dev/null
+++ b/osc.py
@@ -0,0 +1,60 @@
+#!/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 pythonosc import dispatcher
+from pythonosc import osc_server
+from pythonosc import udp_client
+
+client = None
+server = None
+dispatcher = dispatcher.Dispatcher()
+
+
+def init_dispatcher(console):
+ dispatcher.map("/loop_toggle", console.loop_toggle_handler)
+ dispatcher.map("/transport_stop", console.transport_stop_handler)
+ dispatcher.map("/transport_play", console.transport_play_handler)
+ dispatcher.map("/ffwd", console.ffwd_handler)
+ dispatcher.map("/rewind", console.rewind_handler)
+ dispatcher.map("/rec_enable_toggle", console.rec_enable_toggle_handler)
+ dispatcher.map('/strip/fader', console.strip_fader_handler)
+ dispatcher.map('/strip/mute', console.strip_mute_handler)
+ dispatcher.map('/strip/solo', console.strip_solo_handler)
+ dispatcher.map('/strip/recenable', console.strip_recenable_handler)
+ dispatcher.map('/master/fader', console.master_fader_handler)
+ dispatcher.map('/strip/pan_stereo_position',
+ console.pan_stereo_position_handler)
+ dispatcher.map('/strip/name', console.strip_name_handler)
+ dispatcher.map('/bank_up', console.bank_up_handler)
+ dispatcher.map('/bank_down', console.bank_down_handler)
+ dispatcher.set_default_handler(console.default_handler)
+
+
+def init_client(ip, port):
+ global client
+ client = udp_client.SimpleUDPClient(ip, port)
+
+
+def init_server(ip, port, console):
+ global server
+ init_dispatcher(console)
+ server = osc_server.ThreadingOSCUDPServer((ip, port), dispatcher)
diff --git a/strips.py b/strips.py
index da656d1..f92a556 100644
--- a/strips.py
+++ b/strips.py
@@ -21,19 +21,93 @@
"""
from faders import Fader
+import osc
+
class Strip():
- def __init__(self, unit, num):
+ def __init__(self, console, num):
+ self.console = console
self.num = 0
- self.mute = None
- self.solo = None
- self.select = None
- self.recenable = False
+ self.mute_button = None
+ self._mute = False
+ self.solo_button = None
+ self._solo = False
+ self.select_button = None
+ self._select = False
+ self._rec = False
self.pan = 0.5
- self.fader = Fader(unit, self)
+ self.fader = Fader(self.console.unit, self)
self.name = None
+ @property
+ def mute_led(self):
+ return self.console.unit.strips[self.num].mute_led
+
+ @property
+ def solo_led(self):
+ return self.console.unit.strips[self.num].solo_led
+
+ @property
+ def sel_led(self):
+ return self.console.unit.strips[self.num].sel_led
+
+ @property
+ def rec_led(self):
+ return self.console.unit.strips[self.num].rec_led
+
+ @property
+ def mute(self):
+ return self._mute
+
+ @mute.setter
+ def mute(self, state):
+ state = bool(state)
+ self._mute = state
+ if state:
+ self.mute_led.turn_on()
+ else:
+ self.mute_led.turn_off()
+
+ @property
+ def solo(self):
+ return self._solo
+
+ @solo.setter
+ def solo(self, state):
+ state = bool(state)
+ self._solo = state
+ if state:
+ self.solo_led.turn_on()
+ else:
+ self.solo_led.turn_off()
+
+ @property
+ def select(self):
+ return self._select
+
+ @select.setter
+ def select(self, state):
+ state = bool(state)
+ self._select = state
+ if state:
+ self.sel_led.turn_on()
+ else:
+ self.sel_led.turn_off()
+
+ @property
+ def rec(self):
+ return self._rec
+
+ @rec.setter
+ def rec(self, state):
+ state = bool(state)
+ self._rec = state
+ if state:
+ self.rec_led.turn_on()
+ else:
+ self.rec_led.turn_off()
+
def send_pan(self, delta):
addr = '/strip/pan_stereo_position'
pan = self.pan + delta * 0.02
@@ -41,7 +115,7 @@ class Strip():
pan = 0
if pan > 1.0:
pan = 1.0
- osc.send_message(addr, (self.num, pan))
+ osc.client.send_message(addr, (self.num, pan))
def recv_pan(self, pan):
print('Pan: {} {}'.format(self.num, pan))