Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / SCClassLibrary / JITLib / GUI / MonitorGui.sc
blobce952b066d75ab836a0b0183e4724d955da6d8d5
1         // basic gui for a proxy, with monitor or not.
3 MonitorGui : JITGui {
5         classvar <>lastOutBus = 99;
7         var <config;
8         var <ampSl, <playBut, <setOutBox, <playNDialogBut, <fadeBox;
10         *initClass {
11                         Class.initClassTree(Spec);
12                         Spec.add(\ampx4, [0, 4, \amp]);
13                         Spec.add(\fadePx, [0, 100, \amp, 0, 0.02]);
14         }
15                 // options can be: \playN, \level, \name, \fade
16         *new { |object, parent, bounds, makeSkip=true, options = #[]|
17                 ^super.newCopyArgs(object, 0, parent, bounds).init(makeSkip, options)
18         }
20         setDefaults { |options|
21                 var minWidth = 0;
22                 config = (
23                         level: options.includes(\level),
24                         playN: options.includes(\playN),
25                         name: options.includes(\name),
26                         fade: options.includes(\fade)
27                 );
29         if (parent.notNil) { skin = skin.copy.put(\margin, 0@0) };
31                 // a lot more negotiations, based on which options should be there
32                 defPos = 10@260;
34                 minWidth = 200;
36                 if (config.level) { minWidth = minWidth + 60 };
37                 if (config.name) { minWidth = minWidth + 60 };
38                 if (config.playN) { minWidth = minWidth + 20 };
39                 if (config.fade) { minWidth = minWidth + 60 };
40                 minSize = minWidth @ (skin.buttonHeight + (skin.margin.y * 2));
41         ///     "MonitorGui-minSize: %\n".postf(minSize);
42         }
44         makeViews { |options|
46                 var fullWid = zone.bounds.width;
47                 var height = zone.bounds.height - (skin.margin.y * 2);
49                 var levelWid = if (config.level, 60, 0);
50                 var nameWid = if (config.name, 60, 0);
51                 var fadeWid = if (config.fade, 60, 0);
52                 var playWid = 40, outWid = 30;
53                 var playNWid = if (config.playN, 20, 0);
55                 var sliderWidth = fullWid - (levelWid + playWid + outWid + playNWid + nameWid + fadeWid) - 4;
57                 zone.decorator.margin_(0@0);
58                 zone.visible_(false);
61                 this.makeVol(sliderWidth + levelWid, height);
62                 this.makePlayOut(playWid, outWid, height);
64                 if(config.playN) { this.makePlayNDialogBut(playNWid, height) };
65                 if (config.name) { this.makeNameView(nameWid, height) };
66                 if (config.fade) { this.makeFade(fadeWid, height) };
67         }
69         accepts { |obj|
70                 ^(obj.isNil or: { obj.isKindOf(NodeProxy) })
71         }
73         makeNameView { |width, height|
74                 nameView = DragSource(zone, Rect(0,0, width, height))
75                         .font_(font).align_(0).resize_(3)
76         }
78         makeFade { |width = 60, height = 18|
79                 fadeBox = EZNumber(zone, width@height, \fade, \fadePx,
80                                 { |num| try { object.fadeTime_(num.value) } },
81                                 try { object.fadeTime } ? 0.02,
82                                 labelWidth: 28,
83                                 numberWidth: width - 28
84                 );
86                 fadeBox.labelView.font_(font).background_(Color.clear);
87                 fadeBox.numberView.font_(font).background_(Color.clear);
88                 fadeBox.view.resize_(3);
89         }
91         makeVol { |width, height|
92                 var showLev = config.level.binaryValue;
94                 ampSl = EZSlider(zone, (width @ height), \vol, \amp,
95                         { arg sl; if(object.notNil) { object.vol_(sl.value) } },
96                         0, false,
97                         labelWidth: showLev * 20,
98                         numberWidth: showLev * 40);
100                 ampSl.labelView.font_(font).align_(0);
101                 ampSl.view.resize_(2);
102         }
104         makePlayOut { |playWid, outWid, height|
106                 playBut = Button(zone, Rect(0,0, playWid, height))
107                         .font_(font).resize_(3)
108                         .states_([
109                                 [ if (config.playN, \playN, \play), skin.fontColor, skin.offColor],
110                                 [ \stop, skin.fontColor, skin.onColor ]
111                         ]);
113                 this.playNMode_(config.playN);
115                 setOutBox = EZNumber(zone, outWid@height, "", [0, lastOutBus, \lin, 1],
116                         { |box, mod|
117                                 if (object.notNil) {
118                                         if (object.monitor.isNil) {
119                                                 "MonitorGui - monitor is nil, cannot set outs yet.".postln;
120                                                 box.string = "-"
121                                         } {
122                                                 object.monitor.out_(box.value.asInteger);
123                                         };
124                                 };
125                         }, 0, labelWidth: 1, unitWidth: 1);     // 1 is workaround for EZNumber resize bug
126                 setOutBox.view.resize_(3);
127                 setOutBox.numberView.font_(font).align_(\center);
128         }
130         makePlayNDialogBut { |playNDWid, height|
132                 playNDialogBut = GUI.button.new(zone, Rect(0,0, playNDWid, height))
133                         .font_(font).resize_(3)
134                         .states_([
135                                 ["-=", skin.fontColor, skin.offColor],
136                                 ["-<", skin.fontColor, skin.onColor]
137                         ])
138                         .action_({ |box, mod|
139                                 if (object.notNil) {
140                                         object.playNDialog(usePlayN:
141                                                 try { object.monitor.usedPlayN } { config.playN }
142                                         )
143                                 };
144                                 box.value_(1 - box.value);
145                         });
146         }
148         playNMode_ { |flag = true|
149                 var playName, stopName, func;
150                 if (flag.isNil) { "MonitorGui.playNMode_ : flag is nil? should not happen.".postln; flag = false };
152                 if (flag) {
153                         playName = \playN; stopName = \stopN; func = { object.playN };
154                 } {
155                         playName = \play; stopName = \stop;   func = { object.play };
156                 };
158                 playBut.states_(
159                         [(playBut.states[0][0] = playName),
160                         (playBut.states[1][0] = stopName) ]);
161                 playBut.refresh;
163                 playBut.action_({ arg btn, modif;
164                         var alt = modif.notNil and: { modif.isAlt };
165                         if(object.notNil) {
166                                 [       {       if (alt) { object.end } { object.stop }; },
167                                         {       if (alt) { object.vol_(0) };
168                                                 func.value;
169                                         }
170                                 ].at(btn.value).value;
171                                 btn.value_((try { object.monitor.isPlaying } ? false).binaryValue);
172                         } {
173                                 "MonitorGui - no proxy to play!".warn;
174                                 btn.value_(0);
175                         }
176                 })
177         }
179         getState {
180                 var isAudio, newState;
181                 var monitor, outs, amps, newHasSeriesOut;
182                 var plays = 0, playsSpread = false;
184                 newState = (
185                         object: nil,
186                         name: \_none_,
187                         isAudio: false,
188                         monPlaying:     0,
189                         vol:            1,
190                         usedPlayN:      false,
191                         playsSpread:    false,
192                         out:            0,
193                         monFade:                0.02
194                 );
196                 if (object.isNil) { ^newState };
198                 newState.putPairs([
199                         \object, object,
200                         \name, object.key,
201                         \isAudio, object.rate == \audio
202                 ]);
204                 monitor = object.monitor;
205                 if (monitor.isNil) {
206                         ^newState
207                 };
210                 newState.putPairs([
211                         \monPlaying,    monitor.isPlaying.binaryValue,
212                         \vol,           monitor.vol,
213                         \usedPlayN,     monitor.usedPlayN,
214                         \out,           monitor.out ? 0,
215                         \playsSpread,   monitor.hasSeriesOuts.not,
216                         \monFade,               monitor.fadeTime
217                 ]);
219                 ^newState;
220         }
222         checkUpdate {
223                 var newState = this.getState;
225 //                      // don't know why early exit suppresses changes in play state. fix later...
226 //              if (newState == prevState) { ^this };
229                 if (newState[\object] != prevState[\object]) {
230                         zone.visible_(newState[\object].notNil);
231                 };
233                 if (newState[\isAudio] != prevState[\isAudio]) {
234                         zone.enabled_(newState[\isAudio]);
235                 };
237                 if (nameView.notNil) {
238                         if (newState[\name] != prevState[\name]) {
239                                 nameView.object_(newState[\object])
240                                         .string_(newState[\name].asString);
241                         };
242                 };
244                 if (newState[\vol] != prevState[\vol]) {
245                         ampSl.value_(newState[\vol]);
246                 };
247                 if (newState[\monPlaying] != prevState[\monPlaying]) {
248                         playBut.value_(newState[\monPlaying]);
249                 };
250                 if (newState[\usedPlayN] != prevState[\usedPlayN]) {
251                         this.playNMode_ (newState[\usedPlayN]);
252                 };
253                 if (newState[\out] != prevState[\out]) {
254                         setOutBox.value_(newState[\out]);
255                 };
257                 if (playNDialogBut.notNil) {
258                         if (newState[\playsSpread] != prevState[\playsSpread]) {
259                         //      "playsSpread: %\n".postf(newState[\playsSpread].binaryValue);
260                                 playNDialogBut.value_(newState[\playsSpread].binaryValue)
261                         }
262                 };
264                 if (fadeBox.notNil) {
265                         if (newState[\monFade] != prevState[\monFade]) {
266                                 fadeBox.value_(newState[\monFade] ? 0.02);
267                         }
268                 };
270                 prevState = newState;
271         }