5813c6e756e1e0461aec050dd825c5b468f03a34
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

1) /* JFlexiPix - Java implementation of FlexiPix output library
2)  *
3)  * Copyright 2010-2011 Stefan Schuermans <stefan blinkenarea org>
4)  *
5)  * This program is free software: you can redistribute it and/or modify
6)  * it under the terms of the GNU General Public License as published by
7)  * the Free Software Foundation, version 3 of the License.
8)  *
9)  *
10)  * This program is distributed in the hope that it will be useful,
11)  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12)  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13)  * GNU General Public License for more details.
14)  *
15)  * You should have received a copy of the GNU Lesser General Public License
16)  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17)  */
18) 
19) package org.blinkenarea.JFlexiPix;
20) 
21) import java.io.*;
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

22) import java.net.*;
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

23) import java.util.*;
24) import java.util.regex.*;
25) 
26) /// configuration parser
27) class Config
28) {
29)   /**
30)    * @brief constructor
31)    * @param[in] display display to configure
32)    * @param[in] messageIf message interface to report messages to or null
33)    */
34)   Config(Display display, MessageIf messageIf)
35)   {
36)     // save constructor parameters
37)     m_display   = display;
38)     m_messageIf = messageIf;
39) 
40)     // compile regular expression patterns
41) 
42)     // empty lines: "   # comment"
43)     m_patternEmpty = Pattern.compile("^" + "\\s*" + "(?:#.*)?" + "$");
44) 
45)     // extract setting and value from "   setting   =   value   # comment"
46)     m_patternLine = Pattern.compile("^" +
47)                                     "\\s*" +
48)                                     "([^\\s=#](?:[^=#]*[^\\s=#])?)" +
49)                                     "\\s*=\\s*" +
50)                                     "([^\\s=#](?:[^=#]*[^\\s=#])?)" +
51)                                     "\\s*" + 
52)                                     "(?:#.*)?" +
53)                                     "$");
54)   }
55) 
56)   /**
57)    * @brief process distributor from config file
58)    *
59)    * @param[in] settingPart2 second half of setting to process
60)    * @param[in] value value of setting
61)    */
62)   void procDistri(String settingPart2, String value)
63)     throws Exception
64)   {
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

65)     int dist, out, pix;
66)     Pixel px;
67) 
68)     // get distributor number
69)     try {
70)       dist = Integer.parseInt(settingPart2);
71)     } catch (NumberFormatException e) {
72)       dist = Constants.distriMaxCnt; // force error in next line
73)     }
74)     if (dist >= Constants.distriMaxCnt)
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

75)       errorExc("invalid distributor number \"" + settingPart2 + "\"" +
76)                String.format(" in line %d of config file", m_lineNo));
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

77) 
78)     // get number of outputs and pixels
79)     px = PixelParser.parsePixel(value); // abuse for "outputs,pixels"
80)     if (px == null)
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

81)       errorExc("invalid distributor size \"" + value + "\"" +
82)                String.format(" in line %d of config file", m_lineNo));
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

83)     out = px.m_x;
84)     if (out >= Constants.outputMaxCnt)
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

85)       errorExc(String.format("invalid number of outputs \"%d\"" +
86)                              " in line %d of config file", out, m_lineNo));
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

87)     pix = px.m_y;
88)     if (pix >= Constants.pixelMaxCnt)
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

89)       errorExc(String.format("invalid number of pixels \"%d\"" +
90)                              " in line %d of config file", pix, m_lineNo));
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

91) 
92)     // check if distributor is already present
93)     if (m_display.m_distris[dist] != null)
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

94)       errorExc(String.format("duplicate definition of distributor \"%d\"" +
95)                              " in line %d of config file", dist, m_lineNo));
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

96) 
97)     // create new distributor
98)     m_display.m_distris[dist] = new Distri(dist, out, pix);
99) 
100)     // count distributors
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

101)     m_display.m_distriCnt++;
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

102)   }
103) 
104)   /**
105)    * @brief process mapping from config file
106)    *
107)    * @param[in] settingPart2 second half of setting to process
108)    * @param[in] value value of setting
109)    */
110)   void procMapping(String settingPart2, String value)
111)     throws Exception
112)   {
Stefan Schuermans implemened mapping parsing

Stefan Schuermans authored 13 years ago

113)     Pattern pattern;
114)     Matcher matcher;
115)     String strDistri, strChannel, strBase, strFactor, strGamma;
116)     int dist;
117)     Distri distri;
118)     Mapping mapping = null;
119)     double base = 0.0, factor = 1.0, gamma = 1.0;
120) 
121)     // split setting part 2 into distributor and channel
122)     pattern = Pattern.compile("^([0-9]+) +([a-z]+)$");
123)     matcher = pattern.matcher(settingPart2);
124)     if (!matcher.find())
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

125)       errorExc("invalid mapping specifier \"" + settingPart2 + "\"" +
126)                String.format(" in line %d of config file", m_lineNo));
Stefan Schuermans implemened mapping parsing

Stefan Schuermans authored 13 years ago

127)     strDistri  = matcher.group(1);
128)     strChannel = matcher.group(2);
129) 
130)     // get distributor number
131)     try {
132)       dist = Integer.parseInt(strDistri);
133)     } catch (NumberFormatException e) {
134)       dist = Constants.distriMaxCnt; // force error in next line
135)     }
136)     if (dist >= Constants.distriMaxCnt)
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

137)       errorExc("invalid distributor number \"" + strDistri + "\"" +
138)                String.format(" in line %d of config file", m_lineNo));
Stefan Schuermans implemened mapping parsing

Stefan Schuermans authored 13 years ago

139) 
140)     // get distributor
141)     distri = m_display.m_distris[dist];
142)     if (distri == null)
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

143)       errorExc(String.format("no distributor with number \"%d\"" +
144)                              " in line %d of config file", dist, m_lineNo));
Stefan Schuermans implemened mapping parsing

Stefan Schuermans authored 13 years ago

145) 
146)     // get channel
147)     if (strChannel.equals("red"))
148)       mapping = distri.m_mapRed;
149)     else if (strChannel.equals("green"))
150)       mapping = distri.m_mapGreen;
151)     else if (strChannel.equals("blue"))
152)       mapping = distri.m_mapBlue;
153)     else
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

154)       errorExc("invalid channel \"" + strChannel + "\"" +
155)                String.format(" in line %d of config file", m_lineNo));
Stefan Schuermans implemened mapping parsing

Stefan Schuermans authored 13 years ago

156) 
157)     // split mapping parameters
158)     pattern = Pattern.compile("^([-+.eE0-9]+) +([-+.eE0-9]+) +([-+.eE0-9]+)$");
159)     matcher = pattern.matcher(value);
160)     if (!matcher.find())
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

161)       errorExc("invalid mapping parameters \"" + value + "\"" +
162)                String.format(" in line %d of config file", m_lineNo));
Stefan Schuermans implemened mapping parsing

Stefan Schuermans authored 13 years ago

163)     strBase   = matcher.group(1);
164)     strFactor = matcher.group(2);
165)     strGamma  = matcher.group(3);
166) 
167)     // parse mapping parameters
168)     try {
169)       base   = Double.parseDouble(strBase);
170)       factor = Double.parseDouble(strFactor);
171)       gamma  = Double.parseDouble(strGamma);
172)     } catch (NumberFormatException e) {
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

173)       errorExc("invalid mapping parameters \"" + value + "\"" +
174)                String.format(" in line %d of config file", m_lineNo), e);
Stefan Schuermans implemened mapping parsing

Stefan Schuermans authored 13 years ago

175)     }
176)     if (gamma <= 0.0)
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

177)       errorExc(String.format("invalid gamma value \"%f\"" +
178)                              " in line %d of config file", gamma, m_lineNo));
Stefan Schuermans implemened mapping parsing

Stefan Schuermans authored 13 years ago

179) 
180)     // update mapping parameters
181)     mapping.set(base, factor, gamma);
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

182)   }
183) 
184)   /**
185)    * @brief process pixel from config file
186)    *
187)    * @param[in] txtPixel text of pixel to process
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

188)    * @param[in] distri distributor
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

189)    * @param[in] dist number of distributor
190)    * @param[in] out number of output
191)    * @param[in] pix number of pixel
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

192)    * @param return if parsing was successful
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

193)    */
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

194)   boolean procPixel(String txtPixel, Distri distri, int dist, int out, int pix)
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

195)   {
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

196)     Pixel pixel;
197)     int idx;
198) 
199)     // get coordinates of pixel
200)     pixel = PixelParser.parsePixel(txtPixel);
201)     if (pixel == null) {
202)       error("invalid pixel \"" + txtPixel + "\"" +
203)             String.format(" in line %d of config file", m_lineNo));
204)       return false;
205)     }
206) 
207)     // check pixel number
208)     if (pix >= Constants.pixelMaxCnt || pix >= distri.m_pixelCnt) {
209)       error(String.format("too many pixels (more than %d)" +
210)                           " in line %d of config file",
211)                           distri.m_pixelCnt, m_lineNo));
212)       return false;
213)     }
214) 
215)     // check that pixel is not yet set
216)     idx = out * distri.m_pixelCnt + pix;
217)     if (distri.m_pixels[idx] != null) {
218)       error(String.format("pixel %d of output %d of distributor %d" +
219)                           " already set to pixel %d,%d" +
220)                           " in line %d of config file",
221)                           pix, out, dist, distri.m_pixels[idx].m_x,
222)                           distri.m_pixels[idx].m_y, m_lineNo));
223)       return false;
224)     }
225) 
226)     // create pixel
227)     distri.m_pixels[idx] = pixel;
228) 
229)     // count pixels in total
230)     m_display.m_pixelCnt++;
231) 
232)     return true;
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

233)   }
234) 
235)   /**
236)    * @brief process output from config file
237)    *
238)    * @param[in] settingPart2 second half of setting to process
239)    * @param[in] value value of setting
240)    */
241)   void procOutput(String settingPart2, String value)
242)     throws Exception
243)   {
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

244)     Pixel px;
245)     int dist, out, pix;
246)     Distri distri;
247)     String [] pixels;
248)     boolean err;
249) 
250)     // get number of distributor and output
251)     px = PixelParser.parsePixel(settingPart2); // abuse for "dist,out"
252)     if (px == null)
253)       errorExc("invalid output specifier \"" + settingPart2 + "\"" +
254)                String.format(" in line %d of config file", m_lineNo));
255)     dist = px.m_x;
256)     if (dist >= Constants.distriMaxCnt)
257)       errorExc(String.format("invalid distributor number \"%d\"" +
258)                              " in line %d of config file", dist, m_lineNo));
259)     out = px.m_y;
260)     if (out >= Constants.outputMaxCnt)
261)       errorExc(String.format("invalid output number \"%d\"" +
262)                              " in line %d of config file", out, m_lineNo));
263) 
264)     // get distributor
265)     distri = m_display.m_distris[dist];
266)     if (distri == null)
267)       errorExc(String.format("no distributor with number \"%d\"" +
268)                              " in line %d of config file", dist, m_lineNo));
269) 
270)     // check output number
271)     if (out >= distri.m_outputCnt)
272)       errorExc(String.format("no output with output number \"%d\"" +
273)                              " in line %d of config file", out, m_lineNo));
274) 
275)     // count outputs
276)     m_display.m_outputCnt++;
277) 
278)     // process pixels
279)     pixels = value.split("\\s+");
280)     err = false;
281)     for (pix = 0; pix < pixels.length; ++pix)
282)       if (!procPixel(pixels[pix], distri, dist, out, pix))
283)         err = true;
284)     if (err)
285)       errorExc(String.format("invalid pixels in line %d of config file",
286)                              m_lineNo));
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

287)   }
288) 
289)   /**
290)    * @brief process setting from config file
291)    *
292)    * @param[in] setting setting to process
293)    * @param[in] value value of setting
294)    */
295)   void procSetting(String setting, String value)
296)     throws Exception
297)   {
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

298)     InetSocketAddress addr;
299)     Pixel pix;
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

300) 
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

301)     // replace all whitespace in setting with spaces
302)     setting = setting.replace('\t', ' ').replace('\r', ' ')
303)                      .replace('\n', ' ').replace('\f', ' ');
304) 
305)     // bind address of UDP output
306)     if (setting.equals("bindAddr")) {
307)       addr = AddrParser.parseAddr(value);
308)       if (addr == null) {
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

309)         errorExc("invalid addess \"" + value + "\" for \"" + setting +
310)                  String.format(" in line %d of config file", m_lineNo));
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

311)       }
312)       info("bind address: " + addr.toString());
313)       m_display.m_bindAddr = addr;
314)       return;
315)     }
316) 
317)     // size of display
318)     if (setting.equals("size")) {
319)       pix = PixelParser.parsePixel(value);
320)       if (pix == null || pix.m_x <= 0 || pix.m_y <= 0) {
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

321)         errorExc("invalid value \"" + value + "\" for \"" + setting +
322)                  String.format(" in line %d of config file", m_lineNo));
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

323)       }
324)       m_display.m_size = pix;
325)       return;
326)     }
327) 
328)     // distributor
329)     if (setting.startsWith("distributor ")) {
330)       procDistri(setting.substring(12), value);
331)       return;
332)     }
333) 
334)     // mapping
335)     if (setting.startsWith("mapping ")) {
336)       procMapping(setting.substring(8), value);
337)       return;
338)     }
339) 
340)     // distributor
341)     if (setting.startsWith("output ")) {
342)       procOutput(setting.substring(7), value);
343)       return;
344)     }
345) 
346)     // unknown setting
Stefan Schuermans implemened mapping parsing

Stefan Schuermans authored 13 years ago

347)     warning("unknown setting \"" + setting + "\"" +
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

348)             String.format(" in line %d of config file", m_lineNo) +
349)             ", ignored");
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

350)   }
351) 
352)   /**
353)    * @brief process line from config file
354)    *
355)    * @param[in] line line to process
356)    */
357)   void procLine(String line)
358)     throws Exception
359)   {
360)     Matcher matcher;
361)     String setting, value;
362) 
363)     // ignore empty lines: "   # comment"
364)     matcher = m_patternEmpty.matcher(line);
365)     if (matcher.find())
366)       return;
367) 
368)     // extract setting and value from "   setting   =   value   # comment"
369)     matcher = m_patternLine.matcher(line);
370)     if (!matcher.find()) {
371)       // line cannot be parsed
372)       if (m_messageIf != null)
373)         m_messageIf.message(MsgType.Warn,
374)                             String.format("invalid line %d in config file," +
Stefan Schuermans implemented fade example, f...

Stefan Schuermans authored 13 years ago

375)                                           " ignored", m_lineNo));
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

376)       return;
377)     }
378)     setting = matcher.group(1);
379)     value   = matcher.group(2);
380) 
381)     // process setting
382)     procSetting(setting, value);
383)   }
384) 
385)   /**
386)    * @brief process config file
387)    *
388)    * @param[in] configFileName name of config file to read
389)    */
390)   void procFile(String configFileName)
391)     throws Exception
392)   {
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

393)     FileReader fr = null;
394)     BufferedReader br = null;
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

395)     String line;
396) 
397)     // check file name
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

398)     if (configFileName.length() == 0)
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

399)       errorExc("no config file specified");
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

400) 
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

401)     info("using config file \"" + configFileName + "\"");
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

402) 
403)     // open file
404)     try {
405)       fr = new FileReader(configFileName);
406)       br = new BufferedReader(fr);
407)     } catch (FileNotFoundException e) {
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

408)       errorExc("cannot open config file \"" + configFileName +
409)                "\" for reading", e);
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

410)     }
411) 
412)     // read lines and process them
413)     m_lineNo = 1;
414)     while ((line = br.readLine()) != null) {
415)       procLine(line);
416)       ++m_lineNo;
417)     }
418) 
419)     // close file
420)     br.close();
421)     fr.close();
422) 
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

423)     info(String.format("%dx%d input format, ", m_display.m_size.m_x,
424)                                                m_display.m_size.m_y) +
425)          String.format("%d distributors, ",    m_display.m_distriCnt ) +
426)          String.format("%d outputs, ",         m_display.m_outputCnt ) +
Stefan Schuermans implemented fade example, f...

Stefan Schuermans authored 13 years ago

427)          String.format("%d pixels",            m_display.m_pixelCnt));
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

428)   }
429) 
430)   /**
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

431)    * @brief report error message
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

432)    * @param[in] txt error text
433)    */
434)   private void error(String txt)
435)   {
436)     if (m_messageIf != null)
437)       m_messageIf.message(MsgType.Err, txt + "\n");
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

438)   }
439) 
440)   /**
441)    * @brief report error message and throw exception
442)    * @param[in] txt error text
443)    */
444)   private void errorExc(String txt)
445)     throws Exception
446)   {
447)     error(txt);
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

448)     throw new Exception(txt);
449)   }
450) 
451)   /**
452)    * @brief report error message and throw exception
453)    * @param[in] txt error text
454)    * @param[in] e reason for error
455)    */
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

456)   private void errorExc(String txt, Exception e)
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

457)     throws Exception
458)   {
Stefan Schuermans remaining parts of config p...

Stefan Schuermans authored 13 years ago

459)     error(txt + ": " + e.getMessage());
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

460)     throw new Exception(txt, e);
461)   }
462) 
463)   /**
464)    * @brief report warning message
465)    * @param[in] txt warning text
466)    */
467)   private void warning(String txt)
468)   {
469)     if (m_messageIf != null)
470)       m_messageIf.message(MsgType.Warn, txt + "\n");
471)   }
472) 
473)   /**
474)    * @brief report information message
475)    * @param[in] txt information text
476)    */
477)   private void info(String txt)
478)   {
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

479)     if (m_messageIf != null)
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

480)       m_messageIf.message(MsgType.Info, txt + "\n");