HelpBrowser: path box becomes a more conventional search box
[supercollider.git] / SCClassLibrary / Common / Control / SerialPort.sc
blob5a28157c89a5cb7bc35de2c23742047a9be184b4
1 SerialPort
3         classvar <>devicePattern, allPorts;
4         var dataptr, semaphore;
6         var <>doneAction;
8         *initClass {
9                 allPorts = Array[];
10                 UI.registerForShutdown({
11                         //                      this.closeAll;
12                         this.cleanupAll;
13                 });
14         }
16         // device listing
17         *devices {
18                 ^(devicePattern ?? {
19                         thisProcess.platform.name.switch(
20                                 \linux,   "/dev/tty[A,S,U]*",
21                                 \osx,     "/dev/tty.*",
22                                 \windows, "COM"
23                         )
24                 }).pathMatch
25         }
26         *listDevices {
27                 this.devices.do(_.postln);
28         }
30         *new {
31                 | port,
32                   baudrate(9600),
33                   databits(8),
34                   stopbit(true),
35                   parity(nil),
36                   crtscts(false),
37                   xonxoff(false)
38                   exclusive(false) |
40                 if (port.isNumber) {
41                         port = this.devices[port] ?? {
42                                 Error("invalid port index").throw;
43                         };
44                 }
46                 ^super.new.initSerialPort(
47                         port,
48                         exclusive,
49                         baudrate,
50                         databits,
51                         stopbit,
52                         ( even: 1, odd: 2 ).at(parity) ? 0,
53                         crtscts,
54                         xonxoff
55                 )
56         }
57         initSerialPort { | ... args |
58                 semaphore = Semaphore(0);
59                 if ( dataptr.isNil ){
60                   this.prOpen(*args);
61                   allPorts = allPorts.add(this);
62                   doneAction = { ("SerialPort"+args[0]+"was closed").postln; };
63 //              CmdPeriod.add(this);
64                 }
65         }
67         isOpen {
68                 ^dataptr.notNil
69         }
70         close {
71                 if (this.isOpen) {
72                         this.prClose;
73                         allPorts.remove(this);
74 //                      CmdPeriod.remove(this);
75                 }
76         }
77         *closeAll {
78                 var ports = allPorts;
79                 allPorts = Array[];
80                 ports.do(_.close);
81         }
83         *cleanupAll {
84                 var ports = allPorts;
85                 allPorts = Array[];
86                 ports.do(_.primCleanup);
87         }
89         // non-blocking read
90         next {
91                 _SerialPort_Next
92                 ^this.primitiveFailed
93         }
94         // blocking read
95         read {
96                 var byte;
97                 while { (byte = this.next).isNil } {
98                         semaphore.wait;
99                 };
100                 ^byte
101         }
102         // rx errors since last query
103         rxErrors {
104                 _SerialPort_RXErrors
105         }
107         // always blocks
108         put { | byte, timeout=0.005 |
109                 if ( dataptr.notNil ){
110                     while { this.prPut(byte).not } {
111                             timeout.wait;
112                             timeout = timeout * 2;
113                     }
114                 }{
115                   "SerialPort not open".warn;
116                 }
117         }
118         putAll { | bytes, timeout=0.005 |
119                 bytes.do { |byte|
120                         this.put(byte, timeout);
121                 }
122         }
124         doDoneAction{
125                 doneAction.value;
126         }
128 //      cmdPeriod {
129 //              // remove waiting threads
130 //              semaphore.clear;
131 //      }
133         // PRIMITIVE
134         prOpen { | ... args | // was: | port, baudRate | but that misses out on all the other args?
135                 _SerialPort_Open
136                 ^this.primitiveFailed
137         }
138         prClose {
139                 _SerialPort_Close
140                 ^this.primitiveFailed
141         }
142         primCleanup {
143                 _SerialPort_Cleanup
144                 ^this.primitiveFailed
145         }
146         prCleanup{
147                 if (this.isOpen) {
148                         this.primCleanup;
149                         allPorts.remove(this);
150                 }
151         }
152         prPut { | byte |
153                 _SerialPort_Put
154                 ^this.primitiveFailed
155         }
156         prDataAvailable {
157                 // callback
158                 semaphore.signal;
159         }
160         prDoneAction {
161                 // callback
162                 this.doDoneAction;
163                 // cleanup the port
164                 this.prCleanup
165         }