source: trunk/TouchOSC_LC/TouchOSC.py @ 22

Revision 22, 7.2 KB checked in by st8, 14 months ago (diff)

LiveOSC:
Added return and master track listeners and calls (see documentation for implementation)
Added device parameters
/live/send <Track> now returns a list of sends and values

TouchOSC_LC
Page 3 now automatically maps to sends and allows toggling and inter-send routing

TouchOSC
Updated LiveControl TouchOSC layout and corresponding config file

Line 
1"""
2    TouchOSC Midi Remote Script
3    Designed by ST8
4"""
5
6import Live
7import RemixNet
8import OSC
9import re
10import os
11from Logger import Logger
12
13class TouchOSC:
14    __module__ = __name__
15    __doc__ = "TouchOSC Midi Remote Script"
16   
17    # Enable Logging
18    _LOG = 0
19   
20    # Track offset
21    tos = 7
22
23    def __init__(self, c_instance):
24        self.c_instance = c_instance
25       
26        self.logger = self._LOG and Logger() or 0
27        self.log("Logging Enabled")
28       
29        local = RemixNet.get_ip()
30        self.log("Ableton IP: " + str(local))
31       
32        # Init all listeners
33        self.cc = []
34        self.cache = []
35       
36        config = open(os.path.expanduser('~') + '/touchosc_config.txt', 'r')
37
38        first = 0
39        for line in config:
40            line = line.rstrip()
41           
42            # First line is remote ip address
43            if first == 0:
44                remote = line
45                self.oscServer = RemixNet.OSCServer(remote, 5001, local, 5000)
46                self.callbackManager = self.oscServer.callbackManager
47                self.oscServer.sendOSC('/touchosc/startup', 1) 
48               
49                first = 1
50            else:
51                if re.search("xy", line):
52                    self.cc.append(line)
53                    self.cc.append(line)
54                    self.cache.append(0)
55                    self.cache.append(0)
56                else:
57                    self.cc.append(line)
58                    self.cache.append(0)
59         
60                self.callbackManager.add(self.callback, line)
61           
62        config.close()
63       
64        self.c_instance.show_message("TouchOSC > Server Started on " + str(local) + ", sending data to: " + str(remote))       
65                               
66        #self.song().add_current_song_time_listener(self.oscServer.processIncomingUDP)
67
68######################################################################   
69       
70    def disconnect(self):
71        self.oscServer.sendOSC('/touchosc/shutdown', 1)
72        self.oscServer.shutdown()
73
74    def connect_script_instances(self, instanciated_scripts):
75        return
76
77    def is_extension(self):
78        return False
79
80    def request_rebuild_midi_map(self):
81        return
82
83    def build_midi_map(self, midi_map_handle):
84        for i in range(0,20):
85            Live.MidiMap.forward_midi_cc(self.handle(), midi_map_handle, 0, i)
86 
87        def send_midi(self, midi_bytes):
88                self.c_instance.send_midi(midi_bytes)
89
90    def receive_midi(self, bytes):
91        cc = self.cc[bytes[1]]
92        val = float(bytes[2])/float(127)
93       
94        if re.search("xy", cc):
95            self.cache[bytes[1]] = bytes[2]
96            xy1 = self.tuple_idx(self.cc, cc)
97           
98            if bytes[1] == xy1:
99                val2 = float(self.cache[bytes[1] + 1])/float(127)
100                self.oscServer.sendOSC(str(self.cc[bytes[1]]), (val, val2))
101            else:
102                val2 = float(self.cache[bytes[1] - 1])/float(127)
103                self.oscServer.sendOSC(str(self.cc[bytes[1]]), (val2, val))
104               
105                self.log("cc: " + str(bytes[1]) + " val: " + str(val) + " cc2: " + str((bytes[1] - 1)) + " val2: " + str(val2) + " control: " + str(self.cc[bytes[1]]))     
106
107        else:
108            self.log("cc: " + str(bytes[1]) + " val: " + str(bytes[2]) + " control: " + str(self.cc[bytes[1]]))
109            self.oscServer.sendOSC(str(self.cc[bytes[1]]), val)
110
111    def can_lock_to_devices(self):
112        return False
113
114    def suggest_input_port(self):
115        return ''
116
117    def suggest_output_port(self):
118        return ''
119
120    def suggest_map_mode(self, cc_no, channel):
121        return Live.MidiMap.MapMode.absolute
122
123    def __handle_display_switch_ids(self, switch_id, value):
124        pass
125
126######################################################################   
127   
128    def update_display(self):
129        if self.oscServer:
130            try:
131                self.oscServer.processIncomingUDP()
132            except:
133                pass
134
135    def refresh_state(self):
136        return   
137   
138######################################################################
139# Helpers
140    def song(self):
141        return self.c_instance.song()
142
143    def handle(self):
144        return self.c_instance.handle()
145       
146    def log(self, msg):
147        if self._LOG == 1:
148            self.logger.log(str(msg))   
149
150    def tuple_idx(self, tuple, obj):
151        for i in xrange(0,len(tuple)):
152            if (tuple[i] == obj):
153                return i
154           
155######################################################################   
156# Main Touch OSC Functions
157    def callback(self, msg):
158        # Sends handler
159        if re.search("/3/multitoggle1/", msg[0]):
160            ids = msg[0].split('/')
161       
162            ret = 5 - int(ids[3])
163            sid = int(ids[4]) - 1
164           
165            if sid >= ret:
166                sid = sid + 1
167           
168            self.log("row: " + str(ret) + " col:" + str(sid))
169       
170            track = self.song().return_tracks[ret]
171            track.mixer_device.sends[sid].value = msg[2]       
172       
173       
174        elif re.search("/3/push", msg[0]):
175            id  = int(msg[0].replace("/3/push", "")) - 1
176           
177            tr  = (id % 6) + self.tos
178            sid = (id / 6)   
179           
180            track = self.song().tracks[tr]
181            track.mixer_device.sends[sid].value = msg[2]
182       
183        elif re.search("/3/toggle", msg[0]):
184            id  = int(msg[0].replace("/3/toggle", "")) - 1
185           
186            tr  = (id % 6) + self.tos
187            sid = (id / 6) + 2
188           
189            self.log("tr: " + str(tr) + " send: " + str(sid))
190           
191            track = self.song().tracks[tr]
192           
193            # Sends
194            track.mixer_device.sends[sid].value = msg[2]
195 
196            tot = 0
197            for s in range(2, len(track.mixer_device.sends)):
198                tot += track.mixer_device.sends[s].value
199
200            if tot > 0:
201                track.mixer_device.volume.value = 0
202            else:
203                track.mixer_device.volume.value = 0.85
204   
205        elif re.search("xy", msg[0]):
206            cc = self.tuple_idx(self.cc, msg[0])
207           
208            val = int(msg[2] * 127)
209            val2 = int(msg[3] * 127)
210           
211            if abs(self.cache[cc] - val) > 0:
212                self.c_instance.send_midi((0xb0, cc, val))
213                self.cache[cc] = val
214               
215                self.log(str(msg[0]) + " cc: " + str(cc) + " val: " + str(val))
216               
217            if abs(self.cache[cc+1] - val2) > 0:
218                self.c_instance.send_midi((0xb0, cc + 1, val2))
219                self.log(str(msg[0]) + " cc2: " + str(cc+1) + " val2: " + str(val2))
220               
221                self.cache[cc+1] = val2
222
223        else:
224            cc = self.tuple_idx(self.cc, msg[0])
225            val = int(msg[2] * 127)
226       
227            self.c_instance.send_midi((0xb0, cc, val))
228
229            self.log(str(msg[0]) + " cc: " + str(cc) + " val: " + str(val))
230
Note: See TracBrowser for help on using the repository browser.