1
+ #!/usr/bin/env python2
2
+ # -*- coding: utf-8 -*-
3
+
1
4
import sys
2
5
import rtmidi
6
+ import signal
7
+ import locale
8
+ locale .setlocale (locale .LC_ALL , '' )
9
+ import curses
10
+
11
+ #from matrix import View
12
+
13
+ class View :
14
+ def __init__ (self , screen , model ):
15
+ self .screen = screen
16
+ self .cursor = [0 ,0 ]
17
+ self .model = model
18
+
19
+ def input_left (self ):
20
+ return 1 + len (self .model .inputs ) * 2
21
+
22
+ def output_top (self ):
23
+ return 1 + len (self .model .inputs )
24
+
25
+ def draw (self ):
26
+ model = self .model
27
+ s = self .screen
28
+ y = 0
29
+ x = self .input_left () - 1
30
+ for i in model .inputs :
31
+ s .move (y , x )
32
+ s .addch (curses .ACS_HLINE )
33
+ s .addstr (y , x + 1 , i )
34
+ y += 1
35
+ max_y = y
36
+ y += len (model .outputs )
37
+ #y = 1
38
+ x = 0
39
+ for o in model .outputs :
40
+ s .addstr (y , x , o )
41
+ y -= 1
42
+ x += 2
43
+
44
+ y = self .output_top () - 1
45
+ for x in range (len (model .outputs )):
46
+ s .move (y , x * 2 )
47
+ s .vline (curses .ACS_VLINE , len (model .outputs ) - x )
48
+
49
+ for y in range (len (model .inputs )):
50
+ for x in range (len (model .outputs )):
51
+ s .move (y , x * 2 )
52
+ s .addch (curses .ACS_PLUS )
53
+ s .addch (curses .ACS_HLINE )
54
+
55
+ for p1 , p2 in model .connections :
56
+ y = model .get_index_in (p1 )
57
+ x = model .get_index_out (p2 ) * 2
58
+ s .move (y ,x )
59
+ s .addch (curses .ACS_DIAMOND )
60
+ s .addstr (y , x , "◊" )
61
+ s .move ( self .output_top () + len (model .outputs ) + 2 , 0 )
62
+
63
+ def set_cursor (self , cursor ):
64
+ s = self .screen
65
+ s .chgat ( cursor [0 ], self .input_left (), len ( self .model .inputs [cursor [0 ]] ), curses .A_REVERSE )
66
+ s .chgat ( len ( self .model .outputs ) - cursor [1 ] + self .output_top () - 1 , 2 * cursor [1 ], len ( self .model .outputs [cursor [1 ]] ), curses .A_REVERSE )
67
+ self .cursor = cursor
68
+ self .screen .move ( cursor [0 ], cursor [1 ] * 2 )
69
+
3
70
4
71
class Devices :
72
+ _instance = None
5
73
def __init__ (self ):
6
- self .inputs = {}
7
74
self .open_inputs = {}
8
75
self .open_outputs = {}
76
+ self .connections = []
77
+ self .load ()
78
+
79
+ @classmethod
80
+ def instance (cls ):
81
+ if cls ._instance is None :
82
+ cls ._instance = cls ()
83
+ return cls ._instance
84
+
85
+ def load (self ):
9
86
self .ins ()
10
87
self .outs ()
11
88
@@ -48,28 +125,31 @@ def __del__(self):
48
125
for rt in self .open_inputs .values ():
49
126
rt .closePort ()
50
127
51
- class Device :
128
+ class DeviceListener :
52
129
channels = [1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 ]
53
- def __init__ (self ):
54
- self .input = devices .input (self .name )
130
+ def __init__ (self , name ):
131
+ self .name = name
132
+ self .input = Devices .instance ().input (self .name )
55
133
self .input .setCallback ( self )
56
- self .output = devices .output (self .name )
134
+ self .output = Devices . instance () .output (self .name )
57
135
self .subs = []
58
136
59
137
def __call__ (self , message ):
60
138
data = message .getRawData ()
61
139
print '\033 [2K' ,
62
- print ' ' .join ([hex (ord (d ))[2 :] for d in data ]), "\r " ,
63
- sys .stdout .flush ()
140
+ print ' ' .join ([hex (ord (d ))[2 :] for d in data ]),
64
141
self .forward (message )
142
+ print "\r " ,
143
+ sys .stdout .flush ()
65
144
66
145
def forward (self , message ):
67
- ch = message .getChannel ()
68
146
for sub in self .subs :
69
- if ch in sub .channels :
70
- sub .send (message )
147
+ if sub .filter ( message ) :
148
+ sub .output . send (message )
71
149
72
150
def send (self , message ):
151
+ data = message .getRawData ()
152
+ print self .name ,
73
153
self .output .sendMessage (message )
74
154
75
155
def send_unison (self , message , channel ):
@@ -78,77 +158,80 @@ def send_unison(self, message, channel):
78
158
self .output .sendMessage (msg )
79
159
80
160
def subscribe (self , other ):
81
- self .subs .append (other )
82
-
83
- def __rshift__ (self , others ):
84
- for other in others :
85
- self .subscribe (other )
86
-
87
- class Deluge (Device ):
88
- name = 'Deluge'
89
-
90
- class BCR (Device ):
91
- name = 'BCR2000'
92
-
93
- class JUNO (Device ):
94
- name = 'JUNO-DS'
95
- channels = [4 ,5 ,6 ,7 ,9 ,11 ]
96
-
97
- class Circuit (Device ):
98
- name = 'Circuit'
99
- channels = [0 ,1 ,2 ,10 ]
100
-
101
- class Phatty (Device ):
102
- name = 'Little Phatty SE II'
103
- channels = [3 ]
104
- #def send(self, message):
105
- # self.send_unison(message, 3)
106
-
107
- devices = Devices ()
108
- deluge = Deluge ()
109
- bcr = BCR ()
110
- juno = JUNO ()
111
- phatty = Phatty ()
112
- circuit = Circuit ()
113
-
114
- deluge >> juno , circuit , phatty
115
- bcr >> phatty ,
116
- juno >> deluge , circuit , phatty
117
-
118
-
119
- """
120
- matrix = (
121
- (deluge, (juno, circuit, phatty)),
122
- (bcr, (phatty,)),
123
- (juno, (deluge, circuit, phatty)),
124
- )
125
-
126
- for device, others in matrix:
127
- for other in others:
128
- device.subscribe(other)
129
- """
130
-
131
- """
132
- deluge.subscribe(juno)
133
- deluge.subscribe(circuit)
134
- deluge.subscribe(phatty)
135
-
136
- bcr.subscribe(phatty)
137
-
138
- juno.subscribe(deluge)
139
- juno.subscribe(phatty)
140
- juno.subscribe(circuit)
141
- """
142
-
143
-
144
-
145
-
146
-
147
- #while True:
148
- # message = device.getMessage(100)
149
- # call(message)
150
-
151
-
152
- print 'HIT ENTER TO EXIT'
153
- sys .stdin .read (1 )
154
-
161
+ if other not in self .subs :
162
+ self .subs .append (other )
163
+
164
+ class Connection :
165
+ def __init__ (self , i , o ):
166
+ self .input = i
167
+ self .output = o
168
+ self .filter = lambda x : True
169
+
170
+ def connect (self ):
171
+ devs = Devices .instance ()
172
+ self .input .subscribe (self )
173
+
174
+ def __eq__ (self , other ):
175
+ return self .input .name == other .input .name and self .output .name == other .output .name
176
+
177
+ class Router :
178
+ def __init__ (self ):
179
+ self .connections = []
180
+ self .listeners = {}
181
+
182
+ def connect (self , i , o , filt = lambda x : True ):
183
+ if i not in self .listeners :
184
+ self .listeners [i ] = DeviceListener (i )
185
+ if o not in self .listeners :
186
+ self .listeners [o ] = DeviceListener (o )
187
+
188
+ i = self .listeners [i ]
189
+ o = self .listeners [o ]
190
+
191
+ new_connection = Connection (i ,o )
192
+ new_connection .filter = filt
193
+ new_connection .connect ()
194
+ for connection in self .connections :
195
+ if connection == new_connection :
196
+ self .connections .remove (connection )
197
+ self .connections .append (new_connection )
198
+
199
+ def main (stdscr ):
200
+ def channel_filter (channels ):
201
+ return lambda x : x .getChannel () in channels
202
+
203
+ devices = Devices .instance ()
204
+ devices .load ()
205
+ router = Router ()
206
+ router .connect ("Deluge" , "Little Phatty SE II" , channel_filter ((3 ,)))
207
+ router .connect ("Deluge" , "Circuit" , channel_filter ((0 ,1 ,2 ,10 ,)))
208
+ router .connect ("Deluge" , "JUNO-DS" , channel_filter ((4 ,5 ,6 ,7 ,9 ,11 ,)))
209
+ router .connect ("JUNO-DS" , "Circuit" , channel_filter ((1 ,2 ,10 ,)))
210
+ router .connect ("JUNO-DS" , "Deluge" , channel_filter ((8 ,)))
211
+ router .connect ("JUNO-DS" , "Little Phatty SE II" , channel_filter ((3 ,)))
212
+ router .connect ("BCR2000" , "Little Phatty SE II" , channel_filter ((3 ,)))
213
+
214
+ def hup (signum , frame ):
215
+ devices .load ()
216
+ signal .signal (signal .SIGHUP , hup )
217
+
218
+ #while True: #debug
219
+ # message = device.getMessage(100)
220
+ # call(message)
221
+
222
+ #ctrl = Controller(devices)
223
+ view = View (stdscr , devices )
224
+
225
+ while True :
226
+ view .draw ()
227
+ #view.set_cursor(ctrl.cursor)
228
+ key = stdscr .getch ()
229
+ if key == ord ('q' ):
230
+ break
231
+ elif key == ord ('r' ):
232
+ stdscr .clear ()
233
+
234
+ #ctrl.key_press(key)
235
+
236
+ if __name__ == '__main__' :
237
+ curses .wrapper (main )
0 commit comments