ebd260fd18d030569f83fba30edafb300b2b18dc
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 implemened mapping parsing

Stefan Schuermans authored 13 years ago

75)       error("invalid distributor number \"" + settingPart2 + "\"" +
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

76)             String.format(" in line %d of config file", m_lineNo));
77) 
78)     // get number of outputs and pixels
79)     px = PixelParser.parsePixel(value); // abuse for "outputs,pixels"
80)     if (px == null)
Stefan Schuermans implemened mapping parsing

Stefan Schuermans authored 13 years ago

81)       error("invalid distributor size \"" + value + "\"" +
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

82)             String.format(" in line %d of config file", m_lineNo));
83)     out = px.m_x;
84)     if (out >= Constants.outputMaxCnt)
85)       error(String.format("invalid number of outputs \"%d\"" +
86)                           " in line %d of config file", out, m_lineNo));
87)     pix = px.m_y;
88)     if (pix >= Constants.pixelMaxCnt)
89)       error(String.format("invalid number of pixels \"%d\"" +
90)                           " in line %d of config file", pix, m_lineNo));
91) 
92)     // check if distributor is already present
93)     if (m_display.m_distris[dist] != null)
94)       error(String.format("duplicate definition of distributor \"%d\"" +
95)                           " in line %d of config file", dist, m_lineNo));
96) 
97)     // create new distributor
98)     m_display.m_distris[dist] = new Distri(dist, out, pix);
99) 
100)     // count distributors
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())
125)       error("invalid mapping specifier \"" + settingPart2 + "\"" +
126)             String.format(" in line %d of config file", m_lineNo));
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)
137)       error("invalid distributor number \"" + strDistri + "\"" +
138)             String.format(" in line %d of config file", m_lineNo));
139) 
140)     // get distributor
141)     distri = m_display.m_distris[dist];
142)     if (distri == null)
143)       error(String.format("no distributor with number \"%d\"" +
144)                           " in line %d of config file", dist, m_lineNo));
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
154)       error("invalid channel \"" + strChannel + "\"" +
155)             String.format(" in line %d of config file", m_lineNo));
156) 
157)     // split mapping parameters
158)     pattern = Pattern.compile("^([-+.eE0-9]+) +([-+.eE0-9]+) +([-+.eE0-9]+)$");
159)     matcher = pattern.matcher(value);
160)     if (!matcher.find())
161)       error("invalid mapping parameters \"" + value + "\"" +
162)             String.format(" in line %d of config file", m_lineNo));
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) {
173)       error("invalid mapping parameters \"" + value + "\"" +
174)             String.format(" in line %d of config file", m_lineNo), e);
175)     }
176)     if (gamma <= 0.0)
177)       error(String.format("invalid gamma value \"%f\"" +
178)                           " in line %d of config file", gamma, m_lineNo));
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
188)    * @param[in] dist number of distributor
189)    * @param[in] out number of output
190)    * @param[in] pix number of pixel
191)    */
192)   void procPixel(String txtPixel, int dist, int out, int pix)
193)     throws Exception
194)   {
195)     // TODO
196)   }
197) 
198)   /**
199)    * @brief process output from config file
200)    *
201)    * @param[in] settingPart2 second half of setting to process
202)    * @param[in] value value of setting
203)    */
204)   void procOutput(String settingPart2, String value)
205)     throws Exception
206)   {
207)     // TODO
208)   }
209) 
210)   /**
211)    * @brief process setting from config file
212)    *
213)    * @param[in] setting setting to process
214)    * @param[in] value value of setting
215)    */
216)   void procSetting(String setting, String value)
217)     throws Exception
218)   {
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

219)     InetSocketAddress addr;
220)     Pixel pix;
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

222)     // replace all whitespace in setting with spaces
223)     setting = setting.replace('\t', ' ').replace('\r', ' ')
224)                      .replace('\n', ' ').replace('\f', ' ');
225) 
226)     // bind address of UDP output
227)     if (setting.equals("bindAddr")) {
228)       addr = AddrParser.parseAddr(value);
229)       if (addr == null) {
230)         error("invalid addess \"" + value + "\" for \"" + setting +
231)               String.format(" in line %d of config file", m_lineNo));
232)       }
233)       info("bind address: " + addr.toString());
234)       m_display.m_bindAddr = addr;
235)       return;
236)     }
237) 
238)     // size of display
239)     if (setting.equals("size")) {
240)       pix = PixelParser.parsePixel(value);
241)       if (pix == null || pix.m_x <= 0 || pix.m_y <= 0) {
242)         error("invalid value \"" + value + "\" for \"" + setting +
243)               String.format(" in line %d of config file", m_lineNo));
244)       }
245)       m_display.m_size = pix;
246)       return;
247)     }
248) 
249)     // distributor
250)     if (setting.startsWith("distributor ")) {
251)       procDistri(setting.substring(12), value);
252)       return;
253)     }
254) 
255)     // mapping
256)     if (setting.startsWith("mapping ")) {
257)       procMapping(setting.substring(8), value);
258)       return;
259)     }
260) 
261)     // distributor
262)     if (setting.startsWith("output ")) {
263)       procOutput(setting.substring(7), value);
264)       return;
265)     }
266) 
267)     // unknown setting
Stefan Schuermans implemened mapping parsing

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

271)   }
272) 
273)   /**
274)    * @brief process line from config file
275)    *
276)    * @param[in] line line to process
277)    */
278)   void procLine(String line)
279)     throws Exception
280)   {
281)     Matcher matcher;
282)     String setting, value;
283) 
284)     // ignore empty lines: "   # comment"
285)     matcher = m_patternEmpty.matcher(line);
286)     if (matcher.find())
287)       return;
288) 
289)     // extract setting and value from "   setting   =   value   # comment"
290)     matcher = m_patternLine.matcher(line);
291)     if (!matcher.find()) {
292)       // line cannot be parsed
293)       if (m_messageIf != null)
294)         m_messageIf.message(MsgType.Warn,
295)                             String.format("invalid line %d in config file," +
296)                                           " ignored\n", m_lineNo));
297)       return;
298)     }
299)     setting = matcher.group(1);
300)     value   = matcher.group(2);
301) 
302)     // process setting
303)     procSetting(setting, value);
304)   }
305) 
306)   /**
307)    * @brief process config file
308)    *
309)    * @param[in] configFileName name of config file to read
310)    */
311)   void procFile(String configFileName)
312)     throws Exception
313)   {
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

316)     String line;
317) 
318)     // check file name
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

319)     if (configFileName.length() == 0)
320)       error("no config file specified");
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

323) 
324)     // open file
325)     try {
326)       fr = new FileReader(configFileName);
327)       br = new BufferedReader(fr);
328)     } catch (FileNotFoundException e) {
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

329)       error("cannot open config file \"" + configFileName +
330)             "\" for reading", e);
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

331)     }
332) 
333)     // read lines and process them
334)     m_lineNo = 1;
335)     while ((line = br.readLine()) != null) {
336)       procLine(line);
337)       ++m_lineNo;
338)     }
339) 
340)     // close file
341)     br.close();
342)     fr.close();
343) 
Stefan Schuermans implemented more parts of c...

Stefan Schuermans authored 13 years ago

344)     info(String.format("%dx%d input format, ", m_display.m_size.m_x,
345)                                                m_display.m_size.m_y) +
346)          String.format("%d distributors, ",    m_display.m_distriCnt ) +
347)          String.format("%d outputs, ",         m_display.m_outputCnt ) +
348)          String.format("%d pixels, ",          m_display.m_pixelCnt) +
349)          "\n");
350)   }
351) 
352)   /**
353)    * @brief report error message and throw exception
354)    * @param[in] txt error text
355)    */
356)   private void error(String txt)
357)     throws Exception
358)   {
359)     if (m_messageIf != null)
360)       m_messageIf.message(MsgType.Err, txt + "\n");
361)     throw new Exception(txt);
362)   }
363) 
364)   /**
365)    * @brief report error message and throw exception
366)    * @param[in] txt error text
367)    * @param[in] e reason for error
368)    */
369)   private void error(String txt, Exception e)
370)     throws Exception
371)   {
372)     if (m_messageIf != null)
373)       m_messageIf.message(MsgType.Err, txt + ": " + e.getMessage() + "\n");
374)     throw new Exception(txt, e);
375)   }
376) 
377)   /**
378)    * @brief report warning message
379)    * @param[in] txt warning text
380)    */
381)   private void warning(String txt)
382)   {
383)     if (m_messageIf != null)
384)       m_messageIf.message(MsgType.Warn, txt + "\n");
385)   }
386) 
387)   /**
388)    * @brief report information message
389)    * @param[in] txt information text
390)    */
391)   private void info(String txt)
392)   {
Stefan Schuermans start of implementation (ha...

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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