1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 Copyright (c) 2013 Tim Blechmann
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #pragma once
22
23 #include "SC_ReplyImpl.hpp"
24 #include <cinttypes>
25
dumpOSCmsg(int inSize,char * inData,bool skipStatus=false)26 static bool dumpOSCmsg(int inSize, char* inData, bool skipStatus = false) {
27 int size;
28 const char* data;
29
30 if (inData[0]) {
31 const char* addr = inData;
32 if (skipStatus) {
33 if (strcmp(addr, "/status") == 0 || strcmp(addr, "status") == 0) // skip /status messages
34 return false; // nothing has been printed
35 }
36
37 data = OSCstrskip(inData);
38 size = inSize - (data - inData);
39 scprintf("[ \"%s\",", addr);
40 } else {
41 scprintf("[ %d,", OSCint(inData));
42 data = inData + 4;
43 size = inSize - 4;
44 }
45
46 sc_msg_iter msg(size, data);
47
48 while (msg.remain()) {
49 char c = msg.nextTag('i');
50 switch (c) {
51 case 'i':
52 scprintf(" %d", msg.geti());
53 break;
54 case 'f':
55 scprintf(" %g", msg.getf());
56 break;
57 case 'd':
58 scprintf(" %g", msg.getd());
59 break;
60 case 's':
61 scprintf(" \"%s\"", msg.gets());
62 break;
63 case '[':
64 scprintf(" [");
65 msg.count++;
66 break;
67 case ']':
68 scprintf(" ]");
69 msg.count++;
70 break;
71 case 'b':
72 scprintf(" DATA[%zu]", msg.getbsize());
73 msg.skipb();
74 break;
75 case 'm': {
76 char midi[4];
77 msg.getb(midi, 4);
78 scprintf(" MIDI[0x%02x 0x%02x 0x%02x 0x%02x]", midi[0], midi[1], midi[2], midi[3]);
79 break;
80 }
81 case 'c':
82 scprintf(" %c", (char)msg.geti());
83 break;
84 case 't':
85 scprintf(" %" PRId64 "", msg.gett());
86 break;
87 case 'T':
88 scprintf(" true");
89 msg.count++;
90 break;
91 case 'F':
92 scprintf(" false");
93 msg.count++;
94 break;
95 case 'I':
96 scprintf(" infinitum");
97 msg.count++;
98 break;
99 case 'N':
100 scprintf(" nil");
101 msg.count++;
102 break;
103 default:
104 scprintf(" !unknown tag '%c' 0x%02x !", isprint(c) ? c : '?', (unsigned char)c & 255);
105 goto leave;
106 }
107 if (msg.remain() && (c != '['))
108 scprintf(",");
109 }
110 leave:
111 scprintf(" ]");
112 return true; // something has been printed
113 }
114
hexdump(int size,char * data)115 static void hexdump(int size, char* data) {
116 char ascii[20];
117 int padsize = (size + 15) & -16;
118 scprintf("size %d\n", size);
119 for (int i = 0; i < padsize; ++i) {
120 if ((i & 15) == 0) {
121 scprintf("%4d ", i);
122 }
123 if (i >= size) {
124 scprintf(" ");
125 ascii[i & 15] = 0;
126 } else {
127 scprintf("%02x ", (unsigned char)data[i] & 255);
128
129 if (isprint(data[i]))
130 ascii[i & 15] = data[i];
131 else
132 ascii[i & 15] = '.';
133 }
134 if ((i & 15) == 15) {
135 ascii[16] = 0;
136 scprintf(" |%s|\n", ascii);
137 } else if ((i & 3) == 3) {
138 scprintf(" ");
139 }
140 }
141 scprintf("\n");
142 }
143
dumpOSCbndl(int indent,int size,char * inData)144 static bool dumpOSCbndl(int indent, int size, char* inData) {
145 char* data = inData + 8;
146 char* dataEnd = inData + size;
147
148 scprintf("[ \"#bundle\", %" PRIu64 ", ", OSCtime(data));
149 data += 8;
150 while (data < dataEnd) {
151 int contentPrinted;
152
153 int32 msgSize = OSCint(data);
154 data += sizeof(int32);
155
156 scprintf("\n");
157 for (int i = 0; i < indent + 1; i++)
158 scprintf(" ");
159
160 if (!strcmp(data, "#bundle"))
161 contentPrinted = dumpOSCbndl(indent + 1, msgSize, data);
162 else
163 contentPrinted = dumpOSCmsg(msgSize, data, true);
164 data += msgSize;
165 if ((data < dataEnd) && contentPrinted)
166 scprintf(",");
167 }
168 scprintf("\n");
169 for (int i = 0; i < indent; i++)
170 scprintf(" ");
171 scprintf("]");
172
173 return true;
174 }
175
dumpOSC(int mode,int size,char * inData)176 static void dumpOSC(int mode, int size, char* inData) {
177 if (mode & 1) {
178 int indent = 0;
179 bool contentPrinted;
180
181 if (strcmp(inData, "#bundle") == 0)
182 contentPrinted = dumpOSCbndl(indent, size, inData);
183 else
184 contentPrinted = dumpOSCmsg(size, inData, true);
185
186 if (contentPrinted)
187 scprintf("\n");
188 }
189
190 if (mode & 2)
191 hexdump(size, inData);
192 }
193
194 #if 0 // debugging code
195 static void DumpReplyAddress(ReplyAddress *inReplyAddress)
196 {
197 scprintf("mAddress %s\n", inReplyAddress->mAddress.to_string().c_str());
198 if (inReplyAddress->mProtocol == kUDP)
199 scprintf("mProtocol UDP\n");
200 else
201 scprintf("mProtocol TCP\n");
202
203 scprintf("mPort %d\n", inReplyAddress->mPort);
204 scprintf("mSocket %d\n", inReplyAddress->mSocket);
205
206 scprintf("mReplyFunc %p\n", (void*)inReplyAddress->mReplyFunc);
207 }
208 #endif
209