Audio/AudioController: Added AlsaPlayer and TimeMachine modules
g0dil [Wed, 24 Oct 2007 09:12:03 +0000 (09:12 +0000)]
AlsaPlayer.py [new file with mode: 0644]
TimeMachine.py [new file with mode: 0644]
config.py
start.sh

diff --git a/AlsaPlayer.py b/AlsaPlayer.py
new file mode 100644 (file)
index 0000000..1c6f47a
--- /dev/null
@@ -0,0 +1,78 @@
+import Actions
+import subprocess
+
+class Player(object):
+
+    def __init__(self):
+        pass
+
+    def _command(self,*command):
+        subprocess.call([ 'alsaplayer' ] + list(command))
+
+    def _get_status(self):
+        status = {}
+        for line in subprocess.Popen(['alsaplayer', '--status'], stdout=subprocess.PIPE).stdout:
+            if not ':' in line: continue
+            k, v = line.split(':',1)
+            status[k.strip()] = v.strip()
+        return status
+
+    def play(self):
+        self._command('--start')
+
+    def pause(self):
+        if self._get_status()['speed'] == '0%':
+            self.speed(1.0)
+        else:
+            self.speed(0.0)
+
+    def stop(self):
+        self._command('--stop')
+
+    def prev(self):
+        self._command('--prev')
+
+    def next(self):
+        self._command('--next')
+
+    def jump(self, n):
+        self._command('--jump', str(n))
+
+    def clear(self):
+        self._command('--clear')
+
+    def add(self, f):
+        self._command('--enqueue', str(f))
+
+    def speed(self, v):
+        self._command('--speed', str(v))
+
+
+class Action(Actions.Action):
+
+    def __init__(self, name, action, player, *args):
+        Actions.Action.__init__(self, name)
+        self._action = action
+        self._player = player
+        self._args = args
+
+    def __call__(self, binding):
+        getattr(self._player, self._action)(*self._args);
+
+class Dispatcher(object):
+
+    def __init__(self, action):
+        self._action = action
+
+    def __call__(self, name, *args):
+        return Action(name, self._action, *args)
+
+Play   = Dispatcher('play')
+Pause  = Dispatcher('pause')
+Stop   = Dispatcher('stop')
+Toggle = Dispatcher('toggle')
+Prev   = Dispatcher('prev')
+Next   = Dispatcher('next')
+Jump   = Dispatcher('jump')
+Clear  = Dispatcher('clear')
+Add    = Dispatcher('add')
diff --git a/TimeMachine.py b/TimeMachine.py
new file mode 100644 (file)
index 0000000..29999ef
--- /dev/null
@@ -0,0 +1,61 @@
+import Views, Actions
+import subprocess, curses
+
+class TimeMachine(Views.View):
+
+    def __init__(self, context, name, x, y, dx, dy, ports, dir, buffer):
+        Views.View.__init__(self, context, name, x, y, dx, dy)
+        nul = file("/dev/null","w")
+        self._tm = subprocess.Popen(["timemachine", "-i", "-t", str(buffer)] + list(ports), cwd=dir, 
+                                    stdin=subprocess.PIPE, stdout=nul, stderr=nul)
+        self._recording = False
+
+    def start(self):
+        if not self._recording:
+            self._tm.stdin.write("start\n")
+            self._recording = True
+            self._redraw()
+
+    def stop(self):
+        if self._recording:
+            self._tm.stdin.write("stop\n")
+            self._recording = False
+            self._redraw()
+
+    def toggle(self):
+        if self._recording:
+            self.stop()
+        else:
+            self.start()
+
+    def _redraw(self, refresh=True):
+        self.win().addstr(1,2,"Status: ")
+        if self._recording:
+            self.win().addstr(1,10, "RECORDING", curses.A_BOLD)
+        else:
+            self.win().addstr(1,10, "Idle     ")
+        if refresh:
+            self.win().refresh()
+
+    def updateView(self, bindings):
+        pass
+
+    def init(self):
+        Views.View.init(self)
+        self._redraw()
+
+class ToggleRecord(Actions.Action):
+
+    def __init__(self, name, tm):
+        Actions.Action.__init__(self, name)
+        self._tm = tm
+
+    def __call__(self, binding):
+        self._tm.toggle()
+        
+    
+def register(viewmanager, context, name, x, y, dx, dy, ports, dir, buffer):
+    tm = TimeMachine(context, name, x, y, dx, dy, ports, dir, buffer)
+    viewmanager.registerView(tm)
+    return tm
+    
index 93d5654..98abe27 100644 (file)
--- a/config.py
+++ b/config.py
@@ -4,7 +4,7 @@ from Actions import Actions as Action, action
 from Views import EventWidget
 from Events import Event
 import main
-import Joyboard, Keyboard, Process
+import Joyboard, Keyboard, Process, TimeMachine, AlsaPlayer
 import Looper, Mixer
 import sys, curses, time, os
 from curses.ascii import alt, ctrl
@@ -190,8 +190,6 @@ looper.set('sync',1)
 mixer_map = Bindings.KeyMap('Mixer & Effects')
 Action.register( Actions.ChangeBindingsRelative( 'mode_mixer', 0, [ mixer_map ] ) )
 
-looper_main_map.add( Binding( Event('jb0',10),  '[Mixer]', Action['mode_mixer'] ) )
-
 mixer = Mixer.register(
     viewmanager = main.viewmanager,
     oscserver = main.oscserver,
@@ -222,6 +220,20 @@ gain = Mixer.register(
     remote  = ('127.0.0.1', 9902),
 )
 
+tm = TimeMachine.register(
+    viewmanager = main.viewmanager,
+
+    context = 'tm',
+    name    = 'TimeMachine',
+    x       = 52,
+    y       =  4,
+    dx      = 23,
+    dy      =  3,
+
+    ports   = ('minimixer:out_left', 'minimixer:out_right'),
+    dir     = 'tm',
+    buffer  = 10)
+
 Action.register( Mixer.AssignController  ( 'mixer_guitar_level', mixer, ctl, 'Guitar', 1 ) )
 Action.register( Mixer.ToggleMuteChannel ( 'mixer_mute_guitar',  mixer, 1 ) )
 Action.register( Mixer.AssignController  ( 'mixer_voice_level',  mixer, ctl, 'Voice', 2 ) )
@@ -230,6 +242,8 @@ Action.register( Mixer.AssignController  ( 'mixer_master_level', mixer, ctl, 'Ma
 Action.register( Mixer.ToggleMuteAll     ( 'mixer_mute_all',     mixer ) )
 Action.register( Mixer.CycleVolume       ( 'mixer_cycle_gain',   gain, 1, ( 0.0, 2.0, 4.0 ) ) )
 
+Action.register( TimeMachine.ToggleRecord( 'tm_rec_toggle', tm ) )
+
 mixer_map.add( Binding( Event('jb0',0),  'Rec',     Action['looper_record'] ) )
 mixer_map.add( Binding( Event('jb0',1),  'Over',    Action['looper_overdub'] ) )
 mixer_map.add( Binding( Event('jb0',2),  'Mult',    Action['looper_multiply'] ) )
@@ -245,12 +259,50 @@ mixer_map.add( Binding( Event('jb0',9), 'Mute',     Action['mixer_mute_all'] ) )
 mixer_map.add( Binding( Event('jb0',13), '(Vol G)', Action['mixer_guitar_level'] ) )
 mixer_map.add( Binding( Event('jb0',14), '(Vol V)', Action['mixer_voice_level'] ) )
 
+mixer_map.add( Binding( Event('jb0',12), 'TM Rec',  Action['tm_rec_toggle'] ) )
+
 mixer.mute(2)
 mixer.assignController( ctl, 'Guitar', 1 )
     
 ###########################################################################
+# Jukebox
+
+player_map = Bindings.KeyMap('JukeBox')
+Action.register( Actions.ChangeBindingsRelative( 'mode_player', 0, [ player_map ] ) )
+
+player = AlsaPlayer.Player()
+
+Action.register( AlsaPlayer.Play  ( 'player_start',  player ) )
+Action.register( AlsaPlayer.Pause ( 'player_pause',  player ) )
+Action.register( AlsaPlayer.Stop  ( 'player_stop',   player ) )
+Action.register( AlsaPlayer.Prev  ( 'player_prev',   player ) )
+Action.register( AlsaPlayer.Next  ( 'player_next',   player ) )
+
+player_stop_map = Bindings.KeyMap()
+
+Action.register( Actions.ChangeBindingsRelative('player_set_stop_map', 1, [player_stop_map] ) )
+
+Action.register( Actions.Macro( 'player_set_playing', [ 'player_start', 'player_set_stop_map' ] ) )
+Action.register( Actions.Macro( 'player_set_stop',    [ 'player_stop', 'unset_this_map' ]       ) )
+
+for i in range(10):
+    Action.register( AlsaPlayer.Jump  ( 'player_jump_%d' % i, player, i+1 ) )
+    Action.register( Actions.Macro( 'player_set_track_%d' % i,
+                                    [ 'player_jump_%d' % i, 'player_set_stop_map' ] ) )
+    player_map.add( Binding( Event('jb0',i), 'Tr %d' % (i+1), Action['player_set_track_%d' % i] ) )
+
+player_map.add( Binding( Event('jb0', 11), 'Prev',  Action['player_prev']        ) )
+player_map.add( Binding( Event('jb0', 12), 'Next',  Action['player_next']        ) )
+player_map.add( Binding( Event('jb0', 13), 'Play',  Action['player_set_playing'] ) )
+player_map.add( Binding( Event('jb0', 14), 'Pause', Action['player_pause']       ) )
+
+player_stop_map.add( Binding( Event('jb0', 13), 'Stop', Action['player_set_stop'] ) )
+
+###########################################################################
 
-mixer_map.add( Binding( Event('jb0',10), '[Loop]', Action['mode_looper'] ) )
+mixer_map.add       ( Binding( Event('jb0',10), '[Loop]',   Action['mode_looper'] ) )
+looper_main_map.add ( Binding( Event('jb0',10), '[JBox]', Action['mode_player']   ) )
+player_map.add      ( Binding( Event('jb0',10), '[Mixer]',  Action['mode_mixer']  ) )
 
 main.keylist.append(global_map)
 main.keylist.append(mixer_map)
index c5c68a5..f90e336 100755 (executable)
--- a/start.sh
+++ b/start.sh
@@ -58,10 +58,13 @@ killall jack-rack
 killall alsamixer
 killall jackminimix
 killall jackd
+killall audiocontroller
+killall alsaplayer
 
-amixer sset Master 80% on
+amixer sset Master 100% on
 amixer sset PCM 100% on
 amixer sset Capture 50% on
+amixer sset 'Capture Mux' 0,1
 
 start 0 25 496 100 "JACK Audio Connection Kit [(default)] Started." \
     qjackctl
@@ -70,24 +73,27 @@ sooperlooper -l 1 -c 1 -t 300 &
 clients="$clients $!"
 
 cd loops
-start 582 25 794 220 "SooperLooper" \
+start 582 25 794 210 "SooperLooper" \
     slgui
 cd ..
 
 cd conf
-# start 0 153 496 600 "JACK Rack (voice) - voice.rack" \
-start 0 153 496 972 "JACK Rack (voice) - voice.rack" \
+start 0 153 496 428 "JACK Rack (voice) - voice.rack" \
     jack-rack -c 1 -s voice voice.rack
-
-# start 0 781 496 344 "JACK Rack (guitar) - guitar.rack" \
-#    jack-rack -c 1 -s guitar guitar.rack
 cd ..
 
+start 88 609 408 98 "AlsaPlayer" \
+    alsaplayer -r -l 0
+clients="$clients $!"
+move 0 735 496 390 "Queue"
+alsaplayer --stop
+alsaplayer --volume 1
+
 start 502 25 74 210 "dpm meter" \
     meterbridge -r 0 -t dpm -n meter alsa_pcm:capture_1 jack_rack_voice:out_1
 
 x=`expr $offset + 1382`
-xterm -fn 6x12 -bg black -fg white -cr white -geometry 88x18+${x}+25 +sb -title Mixer \
+xterm -fn 6x12 -bg black -fg white -cr white -geometry 88x17+${x}+25 +sb -title Mixer \
     -e alsamixer -V all &
 clients="$clients $!"