diff --git a/app/lib/RXTXcomm.jar b/app/lib/RXTXcomm.jar new file mode 100644 index 000000000..84e5f01df Binary files /dev/null and b/app/lib/RXTXcomm.jar differ diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 8513eaa07..007d60e50 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -286,7 +286,7 @@ public class Base { // Get paths for the libraries and examples in the Processing folder //String workingDirectory = System.getProperty("user.dir"); examplesFolder = getContentFile("examples"); - librariesFolder = getContentFile("libraries"); + librariesFolder = new File(getContentFile("hardware"), "libraries"); toolsFolder = getContentFile("tools"); // Get the sketchbook path, and make sure it's set properly @@ -1109,11 +1109,11 @@ public class Base { for (String libraryName : list) { File subfolder = new File(folder, libraryName); - File libraryFolder = new File(subfolder, "library"); - File libraryJar = new File(libraryFolder, libraryName + ".jar"); - // If a .jar file of the same prefix as the folder exists - // inside the 'library' subfolder of the sketch - if (libraryJar.exists()) { +// File libraryFolder = new File(subfolder, "library"); +// File libraryJar = new File(libraryFolder, libraryName + ".jar"); +// // If a .jar file of the same prefix as the folder exists +// // inside the 'library' subfolder of the sketch +// if (libraryJar.exists()) { String sanityCheck = Sketch.sanitizeName(libraryName); if (!sanityCheck.equals(libraryName)) { String mess = @@ -1124,35 +1124,37 @@ public class Base { continue; } - // get the path for all .jar files in this code folder - String libraryClassPath = - Compiler.contentsToClassPath(libraryFolder); - // grab all jars and classes from this folder, - // and append them to the library classpath - librariesClassPath += - File.pathSeparatorChar + libraryClassPath; - // need to associate each import with a library folder - String packages[] = - Compiler.packageListFromClassPath(libraryClassPath); +// // get the path for all .jar files in this code folder +// String libraryClassPath = +// Compiler.contentsToClassPath(libraryFolder); +// // grab all jars and classes from this folder, +// // and append them to the library classpath +// librariesClassPath += +// File.pathSeparatorChar + libraryClassPath; +// // need to associate each import with a library folder +// String packages[] = +// Compiler.packageListFromClassPath(libraryClassPath); + String packages[] = Compiler.headerListFromIncludePath(subfolder.getAbsolutePath()); for (String pkg : packages) { - importToLibraryTable.put(pkg, libraryFolder); + importToLibraryTable.put(pkg, subfolder); } JMenuItem item = new JMenuItem(libraryName); item.addActionListener(listener); - item.setActionCommand(libraryJar.getAbsolutePath()); +// item.setActionCommand(libraryJar.getAbsolutePath()); menu.add(item); ifound = true; - } else { // not a library, but is still a folder, so recurse - JMenu submenu = new JMenu(libraryName); - // needs to be separate var, otherwise would set ifound to false - boolean found = addLibraries(submenu, subfolder); - if (found) { - menu.add(submenu); - ifound = true; - } - } +// XXX: DAM: should recurse here so that library folders can be nested +// } else { // not a library, but is still a folder, so recurse +// JMenu submenu = new JMenu(libraryName); +// // needs to be separate var, otherwise would set ifound to false +// boolean found = addLibraries(submenu, subfolder); +// if (found) { +// menu.add(submenu); +// ifound = true; +// } +// } } return ifound; } diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index b8aeaab87..8b9922de1 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -42,6 +42,8 @@ import javax.swing.event.*; import javax.swing.text.*; import javax.swing.undo.*; +import gnu.io.*; + /** * Main editor panel for the Processing Development Environment. @@ -75,9 +77,12 @@ public class Editor extends JFrame implements RunnerListener { PageFormat pageFormat; PrinterJob printerJob; - // file and sketch menus for re-inserting items + // file, sketch, and tools menus for re-inserting items JMenu fileMenu; JMenu sketchMenu; + JMenu toolsMenu; + + int numTools = 0; EditorToolbar toolbar; // these menus are shared so that they needn't be rebuilt for all windows @@ -86,6 +91,14 @@ public class Editor extends JFrame implements RunnerListener { static JMenu sketchbookMenu; static JMenu examplesMenu; static JMenu importMenu; + + // these menus are shared so that the board and serial port selections + // are the same for all windows (since the board and serial port that are + // actually used are determined by the preferences, which are shared) + static JMenu boardsMenu; + static JMenu serialMenu; + + static SerialMenuListener serialMenuListener; EditorHeader header; EditorStatus status; @@ -152,6 +165,8 @@ public class Editor extends JFrame implements RunnerListener { fileMenu.insert(sketchbookMenu, 2); fileMenu.insert(examplesMenu, 3); sketchMenu.insert(importMenu, 4); + toolsMenu.insert(boardsMenu, numTools); + toolsMenu.insert(serialMenu, numTools + 1); } }); @@ -595,13 +610,64 @@ public class Editor extends JFrame implements RunnerListener { protected JMenu buildToolsMenu() { - JMenu menu = new JMenu("Tools"); + toolsMenu = new JMenu("Tools"); + JMenu menu = toolsMenu; + JMenuItem item; addInternalTools(menu); addTools(menu, Base.getToolsFolder()); File sketchbookTools = new File(Base.getSketchbookFolder(), "tools"); addTools(menu, sketchbookTools); + menu.addSeparator(); + + numTools = menu.getItemCount(); + + // XXX: DAM: these should probably be implemented using the Tools plugin + // API, if possible (i.e. if it supports custom actions, etc.) + + if (boardsMenu == null) { + boardsMenu = new JMenu("Board"); + ButtonGroup boardGroup = new ButtonGroup(); + for (Iterator i = Preferences.getSubKeys("boards"); i.hasNext(); ) { + String board = (String) i.next(); + Action action = new BoardMenuAction(board); + item = new JRadioButtonMenuItem(action); + if (board.equals(Preferences.get("board"))) + item.setSelected(true); + boardGroup.add(item); + boardsMenu.add(item); + } + } + menu.add(boardsMenu); + + if (serialMenuListener == null) + serialMenuListener = new SerialMenuListener(); + if (serialMenu == null) + serialMenu = new JMenu("Serial Port"); + populateSerialMenu(); + menu.add(serialMenu); + + menu.addSeparator(); + + JMenu bootloaderMenu = new JMenu("Burn Bootloader"); + for (Iterator i = Preferences.getSubKeys("programmers"); i.hasNext(); ) { + String programmer = (String) i.next(); + Action action = new BootloaderMenuAction(programmer); + item = new JMenuItem(action); + bootloaderMenu.add(item); + } + menu.add(bootloaderMenu); + + menu.addMenuListener(new MenuListener() { + public void menuCanceled(MenuEvent e) {} + public void menuDeselected(MenuEvent e) {} + public void menuSelected(MenuEvent e) { + //System.out.println("Tools menu selected."); + populateSerialMenu(); + } + }); + return menu; } @@ -777,6 +843,113 @@ public class Editor extends JFrame implements RunnerListener { } + class SerialMenuListener implements ActionListener { + //public SerialMenuListener() { } + + public void actionPerformed(ActionEvent e) { + if(serialMenu == null) { + System.out.println("serialMenu is null"); + return; + } + int count = serialMenu.getItemCount(); + for (int i = 0; i < count; i++) { + ((JCheckBoxMenuItem)serialMenu.getItem(i)).setState(false); + } + JCheckBoxMenuItem item = (JCheckBoxMenuItem)e.getSource(); + item.setState(true); + String name = item.getText(); + //System.out.println(item.getLabel()); + Preferences.set("serial.port", name); + //System.out.println("set to " + get("serial.port")); + } + + /* + public void actionPerformed(ActionEvent e) { + System.out.println(e.getSource()); + String name = e.getActionCommand(); + PdeBase.properties.put("serial.port", name); + System.out.println("set to " + get("serial.port")); + //editor.skOpen(path + File.separator + name, name); + // need to push "serial.port" into PdeBase.properties + } + */ + } + + + class BoardMenuAction extends AbstractAction { + private String board; + public BoardMenuAction(String board) { + super(Preferences.get("boards." + board + ".name")); + this.board = board; + } + public void actionPerformed(ActionEvent actionevent) { + //System.out.println("Switching to " + board); + Preferences.set("board", board); + } + } + + class BootloaderMenuAction extends AbstractAction { + private String programmer; + public BootloaderMenuAction(String programmer) { + super("w/ " + Preferences.get("programmers." + programmer + ".name")); + this.programmer = programmer; + } + public void actionPerformed(ActionEvent actionevent) { + // XXX: DAM: need to actually burn the bootloader here. + // handleBurnBootloader(programmer); + } + } + + + protected void populateSerialMenu() { + // getting list of ports + + JMenuItem rbMenuItem; + + //System.out.println("Clearing serial port menu."); + + serialMenu.removeAll(); + boolean empty = true; + + try + { + for (Enumeration enumeration = CommPortIdentifier.getPortIdentifiers(); enumeration.hasMoreElements();) + { + CommPortIdentifier commportidentifier = (CommPortIdentifier)enumeration.nextElement(); + //System.out.println("Found communication port: " + commportidentifier); + if (commportidentifier.getPortType() == CommPortIdentifier.PORT_SERIAL) + { + //System.out.println("Adding port to serial port menu: " + commportidentifier); + String curr_port = commportidentifier.getName(); + rbMenuItem = new JCheckBoxMenuItem(curr_port, curr_port.equals(Preferences.get("serial.port"))); + rbMenuItem.addActionListener(serialMenuListener); + //serialGroup.add(rbMenuItem); + serialMenu.add(rbMenuItem); + empty = false; + } + } + if (!empty) { + //System.out.println("enabling the serialMenu"); + serialMenu.setEnabled(true); + } + + } + + catch (Exception exception) + { + System.out.println("error retrieving port list"); + exception.printStackTrace(); + } + + if (serialMenu.getItemCount() == 0) { + serialMenu.setEnabled(false); + } + + //serialMenu.addSeparator(); + //serialMenu.add(item); + } + + protected JMenu buildHelpMenu() { JMenu menu = new JMenu("Help"); JMenuItem item; @@ -1548,7 +1721,7 @@ public class Editor extends JFrame implements RunnerListener { internalCloseRunner(); running = true; toolbar.activate(EditorToolbar.RUN); - statusEmpty(); + statusNotice("Compiling..."); // do this to advance/clear the terminal window / dos prompt / etc for (int i = 0; i < 10; i++) System.out.println(); @@ -1560,30 +1733,24 @@ public class Editor extends JFrame implements RunnerListener { presenting = present; - try { - // XXX: DAM: don't hardcode this to "arduino" - String appletClassName = sketch.compile( - new Target(Base.getHardwarePath() + File.separator + "cores", - "arduino")); - if (appletClassName != null) { - runtime = new Runner(sketch, appletClassName, presenting, Editor.this); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + try { + sketch.compile(new Target( + Base.getHardwarePath() + File.separator + "cores", + Preferences.get("boards." + Preferences.get("board") + ".build.core"))); + statusNotice("Done compiling."); + } catch (RunnerException e) { + //statusError("Error compiling..."); + statusError(e); - // Cannot use invokeLater() here, otherwise it gets - // placed on the event thread and causes a hang--bad idea all around. - Thread t = new Thread(new Runnable() { - public void run() { - runtime.launch(); - } - }); - t.start(); - //runtime.start(appletLocation); + } catch (Exception e) { + e.printStackTrace(); + } + + toolbar.deactivate(EditorToolbar.RUN); } - - } catch (Exception e) { - //System.err.println("exception reached editor"); - //e.printStackTrace(); - statusError(e); - } + }); } @@ -1960,24 +2127,38 @@ public class Editor extends JFrame implements RunnerListener { * Made synchronized to (hopefully) avoid problems of people * hitting export twice, quickly, and horking things up. */ + /** + * Handles calling the export() function on sketch, and + * queues all the gui status stuff that comes along with it. + * + * Made synchronized to (hopefully) avoid problems of people + * hitting export twice, quickly, and horking things up. + */ synchronized public void handleExport() { if (!handleExportCheckModified()) return; toolbar.activate(EditorToolbar.EXPORT); + console.clear(); + statusNotice("Uploading to I/O Board..."); + //SwingUtilities.invokeLater(new Runnable() { Thread t = new Thread(new Runnable() { public void run() { try { - boolean success = sketch.exportApplet(); + boolean success = sketch.exportApplet(new Target( + Base.getHardwarePath() + File.separator + "cores", + Preferences.get("boards." + Preferences.get("board") + ".build.core"))); if (success) { - File appletFolder = new File(sketch.getFolder(), "applet"); - Base.openFolder(appletFolder); - statusNotice("Done exporting."); + statusNotice("Done uploading."); } else { // error message will already be visible } - } catch (Exception e) { + } catch (RunnerException e) { + //statusError("Error during upload."); + //e.printStackTrace(); statusError(e); + } catch (Exception e) { + e.printStackTrace(); } //toolbar.clear(); toolbar.deactivate(EditorToolbar.EXPORT); diff --git a/app/src/processing/app/Serial.java b/app/src/processing/app/Serial.java new file mode 100755 index 000000000..0baab4546 --- /dev/null +++ b/app/src/processing/app/Serial.java @@ -0,0 +1,617 @@ +/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + PSerial - class for serial port goodness + Part of the Processing project - http://processing.org + + Copyright (c) 2004 Ben Fry & Casey Reas + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA +*/ + +package processing.app; +//import processing.core.*; + +import gnu.io.*; + +import java.io.*; +import java.util.*; + + +public class Serial implements SerialPortEventListener { + + //PApplet parent; + + // properties can be passed in for default values + // otherwise defaults to 9600 N81 + + // these could be made static, which might be a solution + // for the classloading problem.. because if code ran again, + // the static class would have an object that could be closed + + SerialPort port; + + int rate; + int parity; + int databits; + int stopbits; + boolean monitor = false; + + // read buffer and streams + + InputStream input; + OutputStream output; + + byte buffer[] = new byte[32768]; + int bufferIndex; + int bufferLast; + + public Serial(boolean monitor) throws SerialException { + this(Preferences.get("serial.port"), + Preferences.getInteger("serial.debug_rate"), + Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + this.monitor = monitor; + } + + public Serial() throws SerialException { + this(Preferences.get("serial.port"), + Preferences.getInteger("serial.debug_rate"), + Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + } + + public Serial(int irate) throws SerialException { + this(Preferences.get("serial.port"), irate, + Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + } + + public Serial(String iname, int irate) throws SerialException { + this(iname, irate, Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + } + + public Serial(String iname) throws SerialException { + this(iname, Preferences.getInteger("serial.debug_rate"), + Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + } + + public Serial(String iname, int irate, + char iparity, int idatabits, float istopbits) + throws SerialException { + //if (port != null) port.close(); + //this.parent = parent; + //parent.attach(this); + + this.rate = irate; + + parity = SerialPort.PARITY_NONE; + if (iparity == 'E') parity = SerialPort.PARITY_EVEN; + if (iparity == 'O') parity = SerialPort.PARITY_ODD; + + this.databits = idatabits; + + stopbits = SerialPort.STOPBITS_1; + if (istopbits == 1.5f) stopbits = SerialPort.STOPBITS_1_5; + if (istopbits == 2) stopbits = SerialPort.STOPBITS_2; + + try { + port = null; + Enumeration portList = CommPortIdentifier.getPortIdentifiers(); + while (portList.hasMoreElements()) { + CommPortIdentifier portId = + (CommPortIdentifier) portList.nextElement(); + + if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { + //System.out.println("found " + portId.getName()); + if (portId.getName().equals(iname)) { + //System.out.println("looking for "+iname); + port = (SerialPort)portId.open("serial madness", 2000); + input = port.getInputStream(); + output = port.getOutputStream(); + port.setSerialPortParams(rate, databits, stopbits, parity); + port.addEventListener(this); + port.notifyOnDataAvailable(true); + //System.out.println("opening, ready to roll"); + } + } + } + } catch (PortInUseException e) { + throw new SerialException("Serial port '" + iname + "' already in use. Try quiting any programs that may be using it."); + } catch (Exception e) { + throw new SerialException("Error opening serial port '" + iname + "'.", e); +// //errorMessage("", e); +// //exception = e; +// //e.printStackTrace(); + } + + if (port == null) { + throw new SerialException("Serial port '" + iname + "' not found. Did you select the right one from the Tools > Serial Port menu?"); + } + } + + + public void setup() { + //parent.registerCall(this, DISPOSE); + } + + + //public void size(int w, int h) { } + + //public void pre() { } + + //public void draw() { } + + //public void post() { } + + //public void mouse(java.awt.event.MouseEvent event) { } + + //public void key(java.awt.event.KeyEvent e) { } + + + public void dispose() { + try { + // do io streams need to be closed first? + if (input != null) input.close(); + if (output != null) output.close(); + + } catch (Exception e) { + e.printStackTrace(); + } + input = null; + output = null; + + try { + if (port != null) port.close(); // close the port + + } catch (Exception e) { + e.printStackTrace(); + } + port = null; + } + + + synchronized public void serialEvent(SerialPortEvent serialEvent) { + //System.out.println("serial port event"); // " + serialEvent); + //System.out.flush(); + //System.out.println("into"); + //System.out.flush(); + //System.err.println("type " + serialEvent.getEventType()); + //System.err.println("ahoooyey"); + //System.err.println("ahoooyeysdfsdfsdf"); + if (serialEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) { + //System.out.println("data available"); + //System.err.flush(); + try { + while (input.available() > 0) { + //if (input.available() > 0) { + //serial = input.read(); + //serialEvent(); + //buffer[bufferCount++] = (byte) serial; + synchronized (buffer) { + if (bufferLast == buffer.length) { + byte temp[] = new byte[bufferLast << 1]; + System.arraycopy(buffer, 0, temp, 0, bufferLast); + buffer = temp; + } + //buffer[bufferLast++] = (byte) input.read(); + if(monitor == true) + System.out.print((char) input.read()); + + /* + System.err.println(input.available() + " " + + ((char) buffer[bufferLast-1])); + */ //} + } + } + //System.out.println("no more"); + + } catch (IOException e) { + errorMessage("serialEvent", e); + //e.printStackTrace(); + //System.out.println("angry"); + } + catch (Exception e) { + } + } + //System.out.println("out of"); + //System.err.println("out of event " + serialEvent.getEventType()); + } + + + /** + * Returns the number of bytes that have been read from serial + * and are waiting to be dealt with by the user. + */ + public int available() { + return (bufferLast - bufferIndex); + } + + + /** + * Ignore all the bytes read so far and empty the buffer. + */ + public void clear() { + bufferLast = 0; + bufferIndex = 0; + } + + + /** + * Returns a number between 0 and 255 for the next byte that's + * waiting in the buffer. + * Returns -1 if there was no byte (although the user should + * first check available() to see if things are ready to avoid this) + */ + public int read() { + if (bufferIndex == bufferLast) return -1; + + synchronized (buffer) { + int outgoing = buffer[bufferIndex++] & 0xff; + if (bufferIndex == bufferLast) { // rewind + bufferIndex = 0; + bufferLast = 0; + } + return outgoing; + } + } + + + /** + * Returns the next byte in the buffer as a char. + * Returns -1, or 0xffff, if nothing is there. + */ + public char readChar() { + if (bufferIndex == bufferLast) return (char)(-1); + return (char) read(); + } + + + /** + * Return a byte array of anything that's in the serial buffer. + * Not particularly memory/speed efficient, because it creates + * a byte array on each read, but it's easier to use than + * readBytes(byte b[]) (see below). + */ + public byte[] readBytes() { + if (bufferIndex == bufferLast) return null; + + synchronized (buffer) { + int length = bufferLast - bufferIndex; + byte outgoing[] = new byte[length]; + System.arraycopy(buffer, bufferIndex, outgoing, 0, length); + + bufferIndex = 0; // rewind + bufferLast = 0; + return outgoing; + } + } + + + /** + * Grab whatever is in the serial buffer, and stuff it into a + * byte buffer passed in by the user. This is more memory/time + * efficient than readBytes() returning a byte[] array. + * + * Returns an int for how many bytes were read. If more bytes + * are available than can fit into the byte array, only those + * that will fit are read. + */ + public int readBytes(byte outgoing[]) { + if (bufferIndex == bufferLast) return 0; + + synchronized (buffer) { + int length = bufferLast - bufferIndex; + if (length > outgoing.length) length = outgoing.length; + System.arraycopy(buffer, bufferIndex, outgoing, 0, length); + + bufferIndex += length; + if (bufferIndex == bufferLast) { + bufferIndex = 0; // rewind + bufferLast = 0; + } + return length; + } + } + + + /** + * Reads from the serial port into a buffer of bytes up to and + * including a particular character. If the character isn't in + * the serial buffer, then 'null' is returned. + */ + public byte[] readBytesUntil(int interesting) { + if (bufferIndex == bufferLast) return null; + byte what = (byte)interesting; + + synchronized (buffer) { + int found = -1; + for (int k = bufferIndex; k < bufferLast; k++) { + if (buffer[k] == what) { + found = k; + break; + } + } + if (found == -1) return null; + + int length = found - bufferIndex + 1; + byte outgoing[] = new byte[length]; + System.arraycopy(buffer, bufferIndex, outgoing, 0, length); + + bufferIndex = 0; // rewind + bufferLast = 0; + return outgoing; + } + } + + + /** + * Reads from the serial port into a buffer of bytes until a + * particular character. If the character isn't in the serial + * buffer, then 'null' is returned. + * + * If outgoing[] is not big enough, then -1 is returned, + * and an error message is printed on the console. + * If nothing is in the buffer, zero is returned. + * If 'interesting' byte is not in the buffer, then 0 is returned. + */ + public int readBytesUntil(int interesting, byte outgoing[]) { + if (bufferIndex == bufferLast) return 0; + byte what = (byte)interesting; + + synchronized (buffer) { + int found = -1; + for (int k = bufferIndex; k < bufferLast; k++) { + if (buffer[k] == what) { + found = k; + break; + } + } + if (found == -1) return 0; + + int length = found - bufferIndex + 1; + if (length > outgoing.length) { + System.err.println("readBytesUntil() byte buffer is" + + " too small for the " + length + + " bytes up to and including char " + interesting); + return -1; + } + //byte outgoing[] = new byte[length]; + System.arraycopy(buffer, bufferIndex, outgoing, 0, length); + + bufferIndex += length; + if (bufferIndex == bufferLast) { + bufferIndex = 0; // rewind + bufferLast = 0; + } + return length; + } + } + + + /** + * Return whatever has been read from the serial port so far + * as a String. It assumes that the incoming characters are ASCII. + * + * If you want to move Unicode data, you can first convert the + * String to a byte stream in the representation of your choice + * (i.e. UTF8 or two-byte Unicode data), and send it as a byte array. + */ + public String readString() { + if (bufferIndex == bufferLast) return null; + return new String(readBytes()); + } + + + /** + * Combination of readBytesUntil and readString. See caveats in + * each function. Returns null if it still hasn't found what + * you're looking for. + * + * If you want to move Unicode data, you can first convert the + * String to a byte stream in the representation of your choice + * (i.e. UTF8 or two-byte Unicode data), and send it as a byte array. + */ + public String readStringUntil(int interesting) { + byte b[] = readBytesUntil(interesting); + if (b == null) return null; + return new String(b); + } + + + /** + * This will handle both ints, bytes and chars transparently. + */ + public void write(int what) { // will also cover char + try { + output.write(what & 0xff); // for good measure do the & + output.flush(); // hmm, not sure if a good idea + + } catch (Exception e) { // null pointer or serial port dead + errorMessage("write", e); + } + } + + + public void write(byte bytes[]) { + try { + output.write(bytes); + output.flush(); // hmm, not sure if a good idea + + } catch (Exception e) { // null pointer or serial port dead + //errorMessage("write", e); + e.printStackTrace(); + } + } + + + /** + * Write a String to the output. Note that this doesn't account + * for Unicode (two bytes per char), nor will it send UTF8 + * characters.. It assumes that you mean to send a byte buffer + * (most often the case for networking and serial i/o) and + * will only use the bottom 8 bits of each char in the string. + * (Meaning that internally it uses String.getBytes) + * + * If you want to move Unicode data, you can first convert the + * String to a byte stream in the representation of your choice + * (i.e. UTF8 or two-byte Unicode data), and send it as a byte array. + */ + public void write(String what) { + write(what.getBytes()); + } + + public void setDTR(boolean state) { + port.setDTR(state); + } + + /** + * If this just hangs and never completes on Windows, + * it may be because the DLL doesn't have its exec bit set. + * Why the hell that'd be the case, who knows. + */ + static public String[] list() { + Vector list = new Vector(); + try { + //System.err.println("trying"); + Enumeration portList = CommPortIdentifier.getPortIdentifiers(); + //System.err.println("got port list"); + while (portList.hasMoreElements()) { + CommPortIdentifier portId = + (CommPortIdentifier) portList.nextElement(); + //System.out.println(portId); + + if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { + String name = portId.getName(); + list.addElement(name); + } + } + + } catch (UnsatisfiedLinkError e) { + //System.err.println("1"); + errorMessage("ports", e); + + } catch (Exception e) { + //System.err.println("2"); + errorMessage("ports", e); + } + //System.err.println("move out"); + String outgoing[] = new String[list.size()]; + list.copyInto(outgoing); + return outgoing; + } + + + /** + * General error reporting, all corraled here just in case + * I think of something slightly more intelligent to do. + */ + static public void errorMessage(String where, Throwable e) { + System.err.println("Error inside Serial." + where + "()"); + e.printStackTrace(); + } +} + + + /* + class SerialMenuListener implements ItemListener { + //public SerialMenuListener() { } + + public void itemStateChanged(ItemEvent e) { + int count = serialMenu.getItemCount(); + for (int i = 0; i < count; i++) { + ((CheckboxMenuItem)serialMenu.getItem(i)).setState(false); + } + CheckboxMenuItem item = (CheckboxMenuItem)e.getSource(); + item.setState(true); + String name = item.getLabel(); + //System.out.println(item.getLabel()); + PdeBase.properties.put("serial.port", name); + //System.out.println("set to " + get("serial.port")); + } + } + */ + + + /* + protected Vector buildPortList() { + // get list of names for serial ports + // have the default port checked (if present) + Vector list = new Vector(); + + //SerialMenuListener listener = new SerialMenuListener(); + boolean problem = false; + + // if this is failing, it may be because + // lib/javax.comm.properties is missing. + // java is weird about how it searches for java.comm.properties + // so it tends to be very fragile. i.e. quotes in the CLASSPATH + // environment variable will hose things. + try { + //System.out.println("building port list"); + Enumeration portList = CommPortIdentifier.getPortIdentifiers(); + while (portList.hasMoreElements()) { + CommPortIdentifier portId = + (CommPortIdentifier) portList.nextElement(); + //System.out.println(portId); + + if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { + //if (portId.getName().equals(port)) { + String name = portId.getName(); + //CheckboxMenuItem mi = + //new CheckboxMenuItem(name, name.equals(defaultName)); + + //mi.addItemListener(listener); + //serialMenu.add(mi); + list.addElement(name); + } + } + } catch (UnsatisfiedLinkError e) { + e.printStackTrace(); + problem = true; + + } catch (Exception e) { + System.out.println("exception building serial menu"); + e.printStackTrace(); + } + + //if (serialMenu.getItemCount() == 0) { + //System.out.println("dimming serial menu"); + //serialMenu.setEnabled(false); + //} + + // only warn them if this is the first time + if (problem && PdeBase.firstTime) { + JOptionPane.showMessageDialog(this, //frame, + "Serial port support not installed.\n" + + "Check the readme for instructions\n" + + "if you need to use the serial port. ", + "Serial Port Warning", + JOptionPane.WARNING_MESSAGE); + } + return list; + } + */ + + + diff --git a/app/src/processing/app/SerialException.java b/app/src/processing/app/SerialException.java new file mode 100644 index 000000000..525c24078 --- /dev/null +++ b/app/src/processing/app/SerialException.java @@ -0,0 +1,39 @@ +/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Copyright (c) 2007 David A. Mellis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app; + +public class SerialException extends Exception { + public SerialException() { + super(); + } + + public SerialException(String message) { + super(message); + } + + public SerialException(String message, Throwable cause) { + super(message, cause); + } + + public SerialException(Throwable cause) { + super(cause); + } +} diff --git a/app/src/processing/app/Sketch.java b/app/src/processing/app/Sketch.java index e92a2e7e7..f4efc8594 100644 --- a/app/src/processing/app/Sketch.java +++ b/app/src/processing/app/Sketch.java @@ -23,11 +23,11 @@ package processing.app; +import processing.app.debug.AvrdudeUploader; import processing.app.debug.Compiler; -import processing.app.debug.Library; -import processing.app.debug.LibraryManager; import processing.app.debug.RunnerException; import processing.app.debug.Target; +import processing.app.debug.Uploader; import processing.app.preproc.*; import processing.core.*; @@ -95,7 +95,7 @@ public class Sketch { * DLLs or JNILIBs. */ private String libraryPath; - public Vector importedLibraries; + private ArrayList importedLibraries; /** * path is location of the main .pde file, because this is also @@ -1310,31 +1310,18 @@ public class Sketch { // grab the imports from the code just preproc'd - importedLibraries = new Vector(); - ArrayList imports = preprocessor.getExtraImports(); - try { - LibraryManager libraryManager = new LibraryManager(); - Collection libraries = libraryManager.getAll(); - for (Iterator i = libraries.iterator(); i.hasNext(); ) { - Library library = (Library) i.next(); - File[] headerFiles = library.getHeaderFiles(); - - for (int j = 0; j < headerFiles.length; j++) - for (int k = 0; k < imports.size(); k++) - if (headerFiles[j].getName().equals(imports.get(k)) && - !importedLibraries.contains(library)) { - importedLibraries.add(library); - //System.out.println("Adding library " + library.getName()); - } + importedLibraries = new ArrayList(); + + for (String item : preprocessor.getExtraImports()) { + File libFolder = (File) Base.importToLibraryTable.get(item); + + if (libFolder != null) { + importedLibraries.add(libFolder); + classPath += Compiler.contentsToClassPath(libFolder); + libraryPath += File.pathSeparator + libFolder.getAbsolutePath(); } - } catch (IOException e) { - System.err.println("Error finding libraries:"); - e.printStackTrace(); - throw new RunnerException(e.getMessage()); } - - // 3. then loop over the code[] and save each .java file for (SketchCode sc : code) { @@ -1385,16 +1372,66 @@ public class Sketch { } - protected boolean exportApplet() throws Exception { - return exportApplet(new File(folder, "applet").getAbsolutePath()); + protected boolean exportApplet(Target target) throws Exception { + return exportApplet(new File(folder, "applet").getAbsolutePath(), target); } /** * Handle export to applet. */ - public boolean exportApplet(String appletPath) throws RunnerException, IOException { - return false; + public boolean exportApplet(String appletPath, Target target) + throws RunnerException, IOException { + + // Make sure the user didn't hide the sketch folder + ensureExistence(); + + // Reload the code when an external editor is being used + if (Preferences.getBoolean("editor.external")) { + // nuke previous files and settings + load(); + } + + File appletFolder = new File(appletPath); + // Nuke the old applet folder because it can cause trouble + if (Preferences.getBoolean("export.delete_target_folder")) { + Base.removeDir(appletFolder); + } + // Create a fresh applet folder (needed before preproc is run below) + appletFolder.mkdirs(); + + // build the sketch + String foundName = build(appletFolder.getPath(), target); + // (already reported) error during export, exit this function + if (foundName == null) return false; + +// // If name != exportSketchName, then that's weirdness +// // BUG unfortunately, that can also be a bug in the preproc :( +// if (!name.equals(foundName)) { +// Base.showWarning("Error during export", +// "Sketch name is " + name + " but the sketch\n" + +// "name in the code was " + foundName, null); +// return false; +// } + + //size(appletFolder.getPath(), name); + upload(appletFolder.getPath(), foundName); + + return true; + } + + protected String upload(String buildPath, String suggestedClassName) + throws RunnerException { + + Uploader uploader; + + // download the program + // + uploader = new AvrdudeUploader(); + boolean success = uploader.uploadUsingPreferences(buildPath, + suggestedClassName); + + return success ? suggestedClassName : null; } /** @@ -1815,6 +1852,11 @@ public class Sketch { } return codeFolder; } + + + public ArrayList getImportedLibraries() { + return importedLibraries; + } public String getClassPath() { diff --git a/app/src/processing/app/debug/AvrdudeUploader.java b/app/src/processing/app/debug/AvrdudeUploader.java new file mode 100755 index 000000000..c74f97f19 --- /dev/null +++ b/app/src/processing/app/debug/AvrdudeUploader.java @@ -0,0 +1,173 @@ +/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + AvrdudeUploader - uploader implementation using avrdude + Part of the Arduino project - http://www.arduino.cc/ + + Copyright (c) 2004-05 + Hernando Barragan + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + $Id$ +*/ + +package processing.app.debug; + +import processing.app.Base; +import processing.app.Preferences; +import processing.app.Serial; + +import java.io.*; +import java.util.*; +import java.util.zip.*; +import javax.swing.*; +import gnu.io.*; + + +public class AvrdudeUploader extends Uploader { + public AvrdudeUploader() { + } + + // XXX: add support for uploading sketches using a programmer + public boolean uploadUsingPreferences(String buildPath, String className) + throws RunnerException { + String uploadUsing = Preferences.get("boards." + Preferences.get("board") + ".upload.using"); + if (uploadUsing == null) { + // fall back on global preference + uploadUsing = Preferences.get("upload.using"); + } + if (uploadUsing.equals("bootloader")) { + return uploadViaBootloader(buildPath, className); + } else { + Collection params = getProgrammerCommands(uploadUsing); + params.add("-Uflash:w:" + buildPath + File.separator + className + ".hex:i"); + return avrdude(params); + } + } + + private boolean uploadViaBootloader(String buildPath, String className) + throws RunnerException { + List commandDownloader = new ArrayList(); + String protocol = Preferences.get("boards." + Preferences.get("board") + ".upload.protocol"); + + // avrdude wants "stk500v1" to distinguish it from stk500v2 + if (protocol.equals("stk500")) + protocol = "stk500v1"; + commandDownloader.add("-c" + protocol); + commandDownloader.add("-P" + (Base.isWindows() ? "\\\\.\\" : "") + Preferences.get("serial.port")); + commandDownloader.add( + "-b" + Preferences.getInteger("boards." + Preferences.get("board") + ".upload.speed")); + commandDownloader.add("-D"); // don't erase + commandDownloader.add("-Uflash:w:" + buildPath + File.separator + className + ".hex:i"); + + if (Preferences.get("boards." + Preferences.get("board") + ".upload.disable_flushing") == null || + Preferences.getBoolean("boards." + Preferences.get("board") + ".upload.disable_flushing") == false) { + flushSerialBuffer(); + } + + return avrdude(commandDownloader); + } + + public boolean burnBootloader(String programmer) throws RunnerException { + return burnBootloader(getProgrammerCommands(programmer)); + } + + private Collection getProgrammerCommands(String programmer) { + List params = new ArrayList(); + params.add("-c" + Preferences.get("programmers." + programmer + ".protocol")); + + if ("usb".equals(Preferences.get("programmers." + programmer + ".communication"))) { + params.add("-Pusb"); + } else if ("serial".equals(Preferences.get("programmers." + programmer + ".communication"))) { + params.add("-P" + (Base.isWindows() ? "\\\\.\\" : "") + Preferences.get("serial.port")); + // XXX: add support for specifying the baud rate for serial programmers. + } + // XXX: add support for specifying the port address for parallel + // programmers, although avrdude has a default that works in most cases. + + if (Preferences.get("programmers." + programmer + ".force") != null && + Preferences.getBoolean("programmers." + programmer + ".force")) + params.add("-F"); + + if (Preferences.get("programmers." + programmer + ".delay") != null) + params.add("-i" + Preferences.get("programmers." + programmer + ".delay")); + + return params; + } + + protected boolean burnBootloader(Collection params) + throws RunnerException { + List fuses = new ArrayList(); + fuses.add("-e"); // erase the chip + fuses.add("-Ulock:w:" + Preferences.get("boards." + Preferences.get("board") + ".bootloader.unlock_bits") + ":m"); + if (Preferences.get("boards." + Preferences.get("board") + ".bootloader.extended_fuses") != null) + fuses.add("-Uefuse:w:" + Preferences.get("boards." + Preferences.get("board") + ".bootloader.extended_fuses") + ":m"); + fuses.add("-Uhfuse:w:" + Preferences.get("boards." + Preferences.get("board") + ".bootloader.high_fuses") + ":m"); + fuses.add("-Ulfuse:w:" + Preferences.get("boards." + Preferences.get("board") + ".bootloader.low_fuses") + ":m"); + + if (!avrdude(params, fuses)) + return false; + + try { + Thread.sleep(1000); + } catch (InterruptedException e) {} + + List bootloader = new ArrayList(); + bootloader.add("-Uflash:w:" + "hardware" + File.separator + "bootloaders" + File.separator + + Preferences.get("boards." + Preferences.get("board") + ".bootloader.path") + + File.separator + Preferences.get("boards." + Preferences.get("board") + ".bootloader.file") + ":i"); + bootloader.add("-Ulock:w:" + Preferences.get("boards." + Preferences.get("board") + ".bootloader.lock_bits") + ":m"); + + return avrdude(params, bootloader); + } + + public boolean avrdude(Collection p1, Collection p2) throws RunnerException { + ArrayList p = new ArrayList(p1); + p.addAll(p2); + return avrdude(p); + } + + public boolean avrdude(Collection params) throws RunnerException { + List commandDownloader = new ArrayList(); + commandDownloader.add("avrdude"); + + // Point avrdude at its config file since it's in a non-standard location. + if (Base.isLinux()) { + // ???: is it better to have Linux users install avrdude themselves, in + // a way that it can find its own configuration file? + commandDownloader.add("-C" + "hardware/tools/avrdude.conf"); + } else { + commandDownloader.add("-C" + Base.getHardwarePath() + "/tools/avr/etc/avrdude.conf"); + } + + if (Preferences.getBoolean("upload.verbose")) { + commandDownloader.add("-v"); + commandDownloader.add("-v"); + commandDownloader.add("-v"); + commandDownloader.add("-v"); + } else { + commandDownloader.add("-q"); + commandDownloader.add("-q"); + } + // XXX: quick hack to chop the "atmega" off of "atmega8" and "atmega168", + // then shove an "m" at the beginning. won't work for attiny's, etc. + commandDownloader.add("-pm" + + Preferences.get("boards." + Preferences.get("board") + ".build.mcu").substring(6)); + commandDownloader.addAll(params); + + return executeUploadCommand(commandDownloader); + } +} diff --git a/app/src/processing/app/debug/Compiler.java b/app/src/processing/app/debug/Compiler.java index 16e9b4515..43a92a6ec 100644 --- a/app/src/processing/app/debug/Compiler.java +++ b/app/src/processing/app/debug/Compiler.java @@ -49,10 +49,12 @@ public class Compiler implements MessageConsumer { public Compiler() { } /** - * Compile with ECJ. + * Compile with avr-gcc. * * @param sketch Sketch object to be compiled. * @param buildPath Where the temporary files live and will be built from. + * @param primaryClassName the name of the combined sketch file w/ extension + * @param target the target (core) to build against * @return true if successful. * @throws RunnerException Only if there's a problem. Only then. */ @@ -67,23 +69,13 @@ public class Compiler implements MessageConsumer { // the pms object isn't used for anything but storage MessageStream pms = new MessageStream(this); - String userdir = System.getProperty("user.dir") + File.separator; - -// LibraryManager libraryManager; -// -// try { -// libraryManager = new LibraryManager(); -// } catch (IOException e) { -// throw new RunnerException(e.getMessage()); -// } String avrBasePath = Base.getAvrBasePath(); List includePaths = new ArrayList(); includePaths.add(target.getPath()); // use lib directories as include paths - for (int i = 0; i < sketch.importedLibraries.size(); i++) { - includePaths.add( - ((Library) sketch.importedLibraries.get(i)).getFolder().getPath()); + for (File file : sketch.getImportedLibraries()) { + includePaths.add(file.getPath()); } List baseCommandLinker = new ArrayList(Arrays.asList(new String[] { @@ -95,75 +87,34 @@ public class Compiler implements MessageConsumer { buildPath + File.separator + primaryClassName + ".elf" })); - String runtimeLibraryName = buildPath + File.separator + "core.a"; +// String runtimeLibraryName = buildPath + File.separator + "core.a"; - List baseCommandAR = new ArrayList(Arrays.asList(new String[] { - avrBasePath + "avr-ar", - "rcs", - runtimeLibraryName - })); +// List baseCommandAR = new ArrayList(Arrays.asList(new String[] { +// avrBasePath + "avr-ar", +// "rcs", +// runtimeLibraryName +// })); - // use lib object files - for (Iterator i = sketch.importedLibraries.iterator(); i.hasNext(); ) { - Library library = (Library) i.next(); - File[] objectFiles = library.getObjectFiles(); - for (int j = 0; j < objectFiles.length; j++) - baseCommandLinker.add(objectFiles[j].getPath()); - } - List baseCommandObjcopy = new ArrayList(Arrays.asList(new String[] { avrBasePath + "avr-objcopy", "-O", "-R", })); - // make list of code files that need to be compiled and the object files - // that they will be compiled to (includes code from the sketch and the - // library for the target platform) - List sourceNames = new ArrayList(); - List sourceNamesCPP = new ArrayList(); - List objectNames = new ArrayList(); - List objectNamesCPP = new ArrayList(); - List targetObjectNames = new ArrayList(); - List sketchObjectNames = new ArrayList(); - - sourceNamesCPP.add(buildPath + File.separator + primaryClassName); - objectNamesCPP.add(buildPath + File.separator + primaryClassName + ".o"); - sketchObjectNames.add(buildPath + File.separator + primaryClassName + ".o"); + ArrayList sourceFiles = new ArrayList(); + ArrayList sourceFilesCPP = new ArrayList(); - for (int i = 0; i < sketch.getCodeCount(); i++) { - //if (sketch.getCode(i).preprocName != null) { - if (sketch.getCode(i).isExtension("c")) { - sourceNames.add(buildPath + File.separator + sketch.getCode(i).getFileName()); - objectNames.add(buildPath + File.separator + sketch.getCode(i).getFileName() + ".o"); - sketchObjectNames.add(buildPath + File.separator + sketch.getCode(i).getFileName() + ".o"); - } else if (sketch.getCode(i).isExtension("cpp")) { - sourceNamesCPP.add(buildPath + File.separator + sketch.getCode(i).getFileName()); - objectNamesCPP.add(buildPath + File.separator + sketch.getCode(i).getFileName() + ".o"); - sketchObjectNames.add(buildPath + File.separator + sketch.getCode(i).getFileName() + ".o"); - } - //} - } - for (Iterator iter = target.getSourceFilenames().iterator(); iter.hasNext(); ) { - String filename = (String) iter.next(); - if (filename != null) { - targetObjectNames.add(buildPath + File.separator + filename + ".o"); - if (filename.endsWith(".c")) { - sourceNames.add(target.getPath() + File.separator + filename); - objectNames.add(buildPath + File.separator + filename + ".o"); - } else if (filename.endsWith(".cpp")) { - sourceNamesCPP.add(target.getPath() + File.separator + filename); - objectNamesCPP.add(buildPath + File.separator + filename + ".o"); - } - } + sourceFiles.addAll(findFilesInPath(buildPath, "c", false)); + sourceFilesCPP.addAll(findFilesInPath(buildPath, "cpp", false)); + + sourceFiles.addAll(findFilesInPath(target.getPath(), "c", true)); + sourceFilesCPP.addAll(findFilesInPath(target.getPath(), "cpp", true)); + + for (File file : sketch.getImportedLibraries()) { + sourceFiles.addAll(findFilesInFolder(file, "c", true)); + sourceFilesCPP.addAll(findFilesInFolder(file, "cpp", true)); } - baseCommandLinker.addAll(sketchObjectNames); - //baseCommandLinker.addAll(targetObjectNames); - baseCommandLinker.add(runtimeLibraryName); - baseCommandLinker.add("-L" + buildPath); - baseCommandLinker.add("-lm"); - firstErrorFound = false; // haven't found any errors yet secondErrorFound = false; @@ -175,24 +126,36 @@ public class Compiler implements MessageConsumer { Process process; boolean compiling = true; - for(int i = 0; i < sourceNames.size(); i++) { + for(File file : sourceFiles) { + String objectPath = buildPath + File.separator + file.getName() + ".o"; + baseCommandLinker.add(objectPath); if (execAsynchronously(getCommandCompilerC(avrBasePath, includePaths, - (String) sourceNames.get(i), (String) objectNames.get(i))) != 0) + file.getAbsolutePath(), + objectPath)) != 0) return false; } - for(int i = 0; i < sourceNamesCPP.size(); i++) { + for(File file : sourceFilesCPP) { + String objectPath = buildPath + File.separator + file.getName() + ".o"; + baseCommandLinker.add(objectPath); if (execAsynchronously(getCommandCompilerCPP(avrBasePath, includePaths, - (String) sourceNamesCPP.get(i), (String) objectNamesCPP.get(i))) != 0) + file.getAbsolutePath(), + objectPath)) != 0) return false; } - for(int i = 0; i < targetObjectNames.size(); i++) { - List commandAR = new ArrayList(baseCommandAR); - commandAR.add(targetObjectNames.get(i)); - if (execAsynchronously(commandAR) != 0) - return false; - } + // XXX: DAM: need to assemble the target files together into a library + // (.a file) before linking the sketch and libraries against it. +// for(File file : findFilesInPath(target.getPath())) { +// List commandAR = new ArrayList(baseCommandAR); +// commandAR.add(file.getAbsolutePath()); +// if (execAsynchronously(commandAR) != 0) +// return false; +// } + + //baseCommandLinker.add(runtimeLibraryName); + //baseCommandLinker.add("-L" + buildPath); + baseCommandLinker.add("-lm"); if (execAsynchronously(baseCommandLinker) != 0) return false; @@ -513,6 +476,29 @@ public class Compiler implements MessageConsumer { return (new File(path)).list(onlyHFiles); } + static public ArrayList findFilesInPath(String path, String extension, + boolean recurse) { + return findFilesInFolder(new File(path), extension, recurse); + } + + static public ArrayList findFilesInFolder(File folder, String extension, + boolean recurse) { + ArrayList files = new ArrayList(); + + for (File file : folder.listFiles()) { + if (file.getName().equals(".") || file.getName().equals("..")) continue; + + if (file.getName().endsWith("." + extension)) + files.add(file); + + if (recurse && file.isDirectory()) { + files.addAll(findFilesInFolder(file, extension, true)); + } + } + + return files; + } + /** * Given a folder, return a list of absolute paths to all jar or zip files * inside that folder, separated by pathSeparatorChar. diff --git a/app/src/processing/app/debug/Library.java b/app/src/processing/app/debug/Library.java deleted file mode 100755 index d7ca98e7a..000000000 --- a/app/src/processing/app/debug/Library.java +++ /dev/null @@ -1,595 +0,0 @@ -/* - Library.java - Library System for Wiring - Copyright (c) 2006 Nicholas Zambetti. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -package processing.app.debug; - -import processing.app.Base; -import processing.app.Preferences; -import processing.app.syntax.*; -import processing.app.debug.RunnerException; - -import java.io.*; -import java.util.*; -import java.util.zip.*; - -import java.awt.*; -import java.awt.event.*; - -import javax.swing.*; -import javax.swing.event.*; - -import processing.core.*; - -/* - * Provides information about and builds a library - */ -public class Library implements MessageConsumer{ - - private File libFolder; - private File utilityFolder; - private LibraryManager libManager; - RunnerException exception; - - static final String BUGS_URL = "https://developer.berlios.de/bugs/?group_id=3590"; - static final String SUPER_BADNESS = "Compiler error, please submit this code to " + BUGS_URL; - - /* - * Create a Library - */ - public Library(LibraryManager manager, File folder) - { - libFolder = folder; - libManager = manager; - utilityFolder = getUtilityFolder(); - - // for debug output - /* - System.out.println("library: " + getName()); - System.out.println("folder: " + getFolder()); - System.out.println("utility: " + utilityFolder); - System.out.println("built: " + isBuilt()); - System.out.println("buildable: " + isBuildable()); - System.out.println("o files: " + getObjectFiles().length); - System.out.println("c files: " + getCSourceFiles().length); - System.out.println("cpp files: " + getCPPSourceFiles().length); - */ - } - - /* - * Directory of library - * @return File object of library's folder - */ - public File getFolder() - { - return libFolder; - } - - /* - * The name of library - * @return String with library name, derived from folder - * note: this will be eventually taken from xml description file - */ - public String getName() - { - return libFolder.getName(); - } - - /* - * Tests if library is built - * @return True if library has .o files, false otherwise - */ - public boolean isBuilt() - { - if(getObjectFiles().length >= (getCSourceFiles().length + getCPPSourceFiles().length)){ - return true; - } - return false; - } - - /* - * Tests if library is buildable - * @return True if library has source files, false otherwise - */ - public boolean isBuildable() - { - if(0 < (getCSourceFiles().length + getCPPSourceFiles().length)){ - return true; - } - return false; - } - - /* - * Tests if library is unbuilt but buildable - * @return True if library has .cpp files but no .o files, false otherwise - */ - public boolean isUnbuiltBuildable() - { - if(isBuildable()){ - if(!isBuilt()){ - return true; - } - } - return false; - } - - /* - * Scans for library "utility" folder - * @return File object of library's "utility" folder, or null - */ - private File getUtilityFolder() - { - FileFilter filter = new FileFilter() { - public boolean accept(File file) { - if(file.isDirectory()){ - if((file.getName()).equalsIgnoreCase("utility")){ - return true; - } - } - return false; - } - }; - File[] files = libFolder.listFiles(filter); - if(files.length > 0){ - return files[0]; - } - return null; - } - - /* - * Finds examples folder - * @return "examples" folder as file object or null - */ - private File getExamplesFolder() - { - FileFilter filter = new FileFilter() { - public boolean accept(File file) { - if(file.isDirectory()){ - if((file.getName()).equalsIgnoreCase("examples")){ - return true; - } - } - return false; - } - }; - File[] files = libFolder.listFiles(filter); - if(files.length > 0){ - return files[0]; - } - return null; - } - - /* - * Populates example menu or submenu with files - */ - private void populateWithExamples(File folder, JMenu menu, ActionListener listener) { - FileFilter onlyfolders = new FileFilter() { - public boolean accept(File file) { - return file.isDirectory(); - } - }; - File[] folders = folder.listFiles(onlyfolders); - File file; - JMenu submenu; - JMenuItem item; - for(int i = 0; i < folders.length; ++i){ - file = new File(folders[i], folders[i].getName() + ".pde"); - if(file.exists()){ - item = new JMenuItem(folders[i].getName()); - item.setActionCommand(file.getAbsolutePath()); - item.addActionListener(listener); - menu.add(item); - }else{ - submenu = new JMenu(folders[i].getName()); - populateWithExamples(folders[i], submenu, listener); - menu.add(submenu); - } - } - } - - /* - * Builds and returns an examples menu - * @return JMenu object with example files, or null if none - */ - public JMenu getExamplesMenu(ActionListener listener) { - JMenu submenu; - File examplesFolder = getExamplesFolder(); - if(null != examplesFolder){ - submenu = new JMenu("Library-" + getName()); - populateWithExamples(examplesFolder, submenu, listener); - return submenu; - } - return null; - } - - /* - * List of object files for linking - * @return Array of object files as File objects - */ - private File[] getObjectFiles(File folder) - { - FileFilter onlyObjectFiles = new FileFilter() { - public boolean accept(File file) { - return (file.getName()).endsWith(".o"); - } - }; - return folder.listFiles(onlyObjectFiles); - } - public File[] getObjectFiles() - { - if(null == utilityFolder){ - return getObjectFiles(libFolder); - } - File[] libraryObjects = getObjectFiles(libFolder); - File[] utilityObjects = getObjectFiles(utilityFolder); - File[] objects = new File[libraryObjects.length + utilityObjects.length]; - System.arraycopy(libraryObjects, 0, objects, 0, libraryObjects.length); - System.arraycopy(utilityObjects, 0, objects, libraryObjects.length, utilityObjects.length); - return objects; - } - - /* - * List of header source files for inclusion - * @return Array of header source files as File objects - */ - public File[] getHeaderFiles() - { - FileFilter onlyHFiles = new FileFilter() { - public boolean accept(File file) { - return (file.getName()).endsWith(".h"); - } - }; - return libFolder.listFiles(onlyHFiles); - } - - /* - * List of library's C source files for compiling - * @return Array of C source files as File objects - */ - private File[] getCSourceFiles(File folder) - { - FileFilter onlyCFiles = new FileFilter() { - public boolean accept(File file) { - return (file.getName()).endsWith(".c"); - } - }; - return folder.listFiles(onlyCFiles); - } - private File[] getCSourceFiles() - { - if(null == utilityFolder){ - return getCSourceFiles(libFolder); - } - File[] librarySources = getCSourceFiles(libFolder); - File[] utilitySources = getCSourceFiles(utilityFolder); - File[] sources = new File[librarySources.length + utilitySources.length]; - System.arraycopy(librarySources, 0, sources, 0, librarySources.length); - System.arraycopy(utilitySources, 0, sources, librarySources.length, utilitySources.length); - return sources; - } - - /* - * List of C++ source files for compiling - * @return Array of C++ source files as File objects - */ - private File[] getCPPSourceFiles(File folder) - { - FileFilter onlyCPPFiles = new FileFilter() { - public boolean accept(File file) { - return (file.getName()).endsWith(".cpp"); - } - }; - return folder.listFiles(onlyCPPFiles); - } - private File[] getCPPSourceFiles() - { - if(null == utilityFolder){ - return getCPPSourceFiles(libFolder); - } - File[] librarySources = getCPPSourceFiles(libFolder); - File[] utilitySources = getCPPSourceFiles(utilityFolder); - File[] sources = new File[librarySources.length + utilitySources.length]; - System.arraycopy(librarySources, 0, sources, 0, librarySources.length); - System.arraycopy(utilitySources, 0, sources, librarySources.length, utilitySources.length); - return sources; - } - - /* - * Attempt to build library - * @return true on successful build, false otherwise - */ - public boolean build() throws RunnerException - { - // fail if library is not buildable (contains no sources) - if(!isBuildable()){ - return false; - } - - String userdir = System.getProperty("user.dir") + File.separator; - String avrBasePath; - if(Base.isMacOS()) { - avrBasePath = new String("hardware/tools/avr/bin/"); - } - else if(Base.isLinux()) { - avrBasePath = new String(""); - } - else { - avrBasePath = new String(userdir + "hardware/tools/avr/bin/"); - } - - String[] baseCompileCommandC = new String[] { - avrBasePath + "avr-gcc", - "-c", - "-g", - "-Os", - "-Wall", - "-ffunction-sections", // place each function in its own section - "-fdata-sections", - "-mmcu=" + Preferences.get("boards." + Preferences.get("board") + ".build.mcu"), - "-DF_CPU=" + Preferences.get("boards." + Preferences.get("board") + ".build.f_cpu"), - "-I" + libManager.getTarget().getPath(), - "-I" + getFolder(), - }; - - String[] baseCompileCommandCPP = new String[] { - avrBasePath + "avr-g++", - "-c", - "-g", - "-Os", - "-Wall", - "-fno-exceptions", - "-ffunction-sections", // place each function in its own section - "-fdata-sections", - "-mmcu=" + Preferences.get("boards." + Preferences.get("board") + ".build.mcu"), - "-DF_CPU=" + Preferences.get("boards." + Preferences.get("board") + ".build.f_cpu"), - "-I" + libManager.getTarget().getPath(), - "-I" + getFolder(), - }; - - // use built lib directories in include paths when searching for headers - // this allows libs to use other libs easily - int extraSpots = 2; // two spots for file path and -o portions - utilityFolder = getUtilityFolder(); // refresh status of utility folder - if(null != utilityFolder){ - extraSpots = 3; // an extra spot for utility folder as include - } - String[] libDirs = libManager.getFolderPaths(); - String[] compileCommandC = new String[baseCompileCommandC.length + libDirs.length + extraSpots]; - String[] compileCommandCPP = new String[baseCompileCommandCPP.length + libDirs.length + extraSpots]; - System.arraycopy(baseCompileCommandC, 0, compileCommandC, 0, baseCompileCommandC.length); - System.arraycopy(baseCompileCommandCPP, 0, compileCommandCPP, 0, baseCompileCommandCPP.length); - for (int i = 0; i < libDirs.length; ++i) { - compileCommandC[baseCompileCommandC.length + i] = "-I" + libDirs[i]; - compileCommandCPP[baseCompileCommandCPP.length + i] = "-I" + libDirs[i]; - } - - // add this library's "utility" folder to inclusion paths - if(null != utilityFolder){ - compileCommandC[compileCommandC.length - 3] = "-I" + utilityFolder.getPath(); - compileCommandCPP[compileCommandCPP.length - 3] = "-I" + utilityFolder.getPath(); - } - - File[] sourcesC = getCSourceFiles(); - File[] sourcesCPP = getCPPSourceFiles(); - - // execute the compiler, and create threads to deal - // with the input and error streams - // - int result = 0; - try { - String pathSansExtension; - Process process; - boolean compiling = true; - - // compile c sources - for(int i = 0; i < sourcesC.length; ++i) { - pathSansExtension = sourcesC[i].getPath(); - pathSansExtension = pathSansExtension.substring(0, pathSansExtension.length() - 2); // -2 because ".c" - - compileCommandC[compileCommandC.length - 2] = sourcesC[i].getPath(); - compileCommandC[compileCommandC.length - 1] = "-o" + pathSansExtension + ".o"; - - process = Runtime.getRuntime().exec(compileCommandC); - new MessageSiphon(process.getInputStream(), this); - new MessageSiphon(process.getErrorStream(), this); - - // wait for the process to finish. if interrupted - // before waitFor returns, continue waiting - // - compiling = true; - while (compiling) { - try { - result = process.waitFor(); - //System.out.println("result is " + result); - compiling = false; - } catch (InterruptedException ignored) { } - } - if (exception != null) { - //exception.hideStackTrace = true; - throw exception; - } - if(result != 0){ - return false; - } - } - - // compile c++ sources - for(int i = 0; i < sourcesCPP.length; ++i) { - pathSansExtension = sourcesCPP[i].getPath(); - pathSansExtension = pathSansExtension.substring(0, pathSansExtension.length() - 4); // -4 because ".cpp" - - compileCommandCPP[compileCommandCPP.length - 2] = sourcesCPP[i].getPath(); - compileCommandCPP[compileCommandCPP.length - 1] = "-o" + pathSansExtension + ".o"; - - process = Runtime.getRuntime().exec(compileCommandCPP); - new MessageSiphon(process.getInputStream(), this); - new MessageSiphon(process.getErrorStream(), this); - - // wait for the process to finish. if interrupted - // before waitFor returns, continue waiting - // - compiling = true; - while (compiling) { - try { - result = process.waitFor(); - //System.out.println("result is " + result); - compiling = false; - } catch (InterruptedException ignored) { } - } - if (exception != null) { - //exception.hideStackTrace = true; - throw exception; - } - if(result != 0){ - return false; - } - } - } catch (Exception e) { - String msg = e.getMessage(); - if ((msg != null) && (msg.indexOf("avr-gcc: not found") != -1)) { - Base.showWarning("Compiler error", - "Could not find the compiler.\n" + - "avr-gcc is missing from your PATH,\n" + - "see readme.txt for help.", null); - return false; - - } else if ((msg != null) && (msg.indexOf("avr-g++: not found") != -1)) { - Base.showWarning("Compiler error", - "Could not find the compiler.\n" + - "avr-g++ is missing from your PATH,\n" + - "see readme.txt for help.", null); - return false; - - } else { - e.printStackTrace(); - result = -1; - } - } - - // an error was queued up by message() - if (exception != null) { - throw exception; - } - - if (result != 0 && result != 1 ) { - Base.openURL(BUGS_URL); - throw new RunnerException(SUPER_BADNESS); - } - - // success would mean that 'result' is set to zero - return (result == 0); // ? true : false; - } - - /** - * Part of the MessageConsumer interface, this is called - * whenever a piece (usually a line) of error message is spewed - * out from the compiler. The errors are parsed for their contents - * and line number, which is then reported back to Editor. - */ - public void message(String inString) { - // This receives messages as full lines, so a newline needs - // to be added as they're printed to the console. - - // always print all compilation output for library writers! - String outString = ""; - - // shorten file paths so that they are friendlier - int start = 0; - int end = 0; - String substring = libFolder.getPath() + File.separator; - StringBuffer result = new StringBuffer(); - while ((end = inString.indexOf(substring, start)) >= 0) { - result.append(inString.substring(start, end)); - start = end + substring.length(); - } - result.append(inString.substring(start)); - outString = result.toString(); - - System.err.print(outString); - - // prepare error for throwing - if (inString.indexOf("error") != -1){ - exception = new RunnerException("Error building library \"" + getName() + "\""); - } - } - - /** - * Handles loading of keywords file. - * It is recommended that a # sign be used for comments - * inside keywords.txt. - */ - public void addSyntaxColors(PdeKeywords keywords) { - File keywordsFile = new File(libFolder.getPath() + File.separator + "keywords.txt"); - - // do not bother if no keywords file to read - // should reprimand negligent library writers?! - if(!keywordsFile.exists() || !keywordsFile.canRead()){ - return; - } - - try{ - // open file stream in the verbose java way - InputStream input = new FileInputStream(keywordsFile); - InputStreamReader isr = new InputStreamReader(input); - BufferedReader reader = new BufferedReader(isr); - - String line = null; - while ((line = reader.readLine()) != null) { - - // skip empty and whitespace lines - if (line.trim().length() == 0){ - continue; - } - - // skip lines without tabs - if (line.indexOf('\t') == -1){ - continue; - } - - String pieces[] = PApplet.split(line, '\t'); - - if (pieces.length >= 2) { - String keyword = pieces[0].trim(); - String coloring = pieces[1].trim(); - - if (coloring.length() > 0) { - // text will be KEYWORD or LITERAL - boolean isKey = (coloring.charAt(0) == 'K'); - - // KEYWORD1 -> 0, KEYWORD2 -> 1, etc - int num = coloring.charAt(coloring.length() - 1) - '1'; - - byte id = (byte)((isKey ? Token.KEYWORD1 : Token.LITERAL1) + num); - - //System.out.println("got " + (isKey ? "keyword" : "literal") + (num+1) + " for " + keyword); - - // XXX: DAM: PdeKeywords.getKeywordColoring().add(keyword, id); - } - } - } - - // close file stream - reader.close(); - } catch (Exception e) { - Base.showError("Problem Loading Keywords", - "Could not load or interpret 'keywords.txt' in " + getName() + " library.\n" + - "This must be corrected before distributing.", e); - } - } - -} diff --git a/app/src/processing/app/debug/LibraryManager.java b/app/src/processing/app/debug/LibraryManager.java deleted file mode 100755 index 8f11ec76d..000000000 --- a/app/src/processing/app/debug/LibraryManager.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - LibraryManager.java - Library System for Wiring - Copyright (c) 2006-07 Nicholas Zambetti. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -package processing.app.debug; - -import processing.app.Base; -import processing.app.Preferences; -import processing.app.syntax.*; -import processing.app.debug.RunnerException; - -import java.io.*; -import java.util.*; -import java.util.zip.*; - -import java.awt.event.*; - -import javax.swing.*; - -/* - * Provides information about and builds libraries - */ -public class LibraryManager { - - private File libDir; - private List libraries = new ArrayList(); - private Target target; - - /* - * Create a LibraryManager. - */ - public LibraryManager() throws IOException - { - String userDir = System.getProperty("user.dir") + File.separator; - libDir = new File(Base.getHardwareFolder(), "libraries"); -// target = new Target( -// System.getProperty("user.dir") + File.separator + "hardware" + -// File.separator + "cores", -// Preferences.get("boards." + Preferences.get("board") + ".build.core")); - target = new Target(Base.getHardwarePath() + File.separator + "cores", - "arduino"); - refreshLibraries(); - } - - public Target getTarget() - { - return target; - } - - /* - * Scans for libraries and refreshes internal list - */ - private void refreshLibraries() - { - FileFilter onlyDirs = new FileFilter() { - public boolean accept(File file) { - return file.isDirectory(); - } - }; - libraries.clear(); - File[] libs = libDir.listFiles(onlyDirs); - for(int i = 0; i < libs.length; ++i){ - libraries.add(new Library(this, libs[i])); - } - } - - /* - * Returns a collection of all library objects - * @return A read-only collection of Library objects - */ - public Collection getAll() { - refreshLibraries(); - return Collections.unmodifiableList(libraries); - } - - /* - * Returns a collection of all built library objects - * @return A read-only collection of built Library objects - */ - public Collection getBuiltLibraries() { - refreshLibraries(); - List builtLibraries = new ArrayList(); - Library library; - ListIterator libIterator = libraries.listIterator(); - while(libIterator.hasNext()){ - library = (Library)libIterator.next(); - if(library.isBuilt()){ - builtLibraries.add(library); - } - } - return Collections.unmodifiableList(builtLibraries); - } - - /* - * Returns a collection of all buildable library objects - * @return A read-only collection of built Library objects - */ - public Collection getLibrariesToBuild() { - refreshLibraries(); - List buildableLibraries = new ArrayList(); - Library library; - ListIterator libIterator = libraries.listIterator(); - while(libIterator.hasNext()){ - library = (Library)libIterator.next(); - if(library.isUnbuiltBuildable()){ - buildableLibraries.add(library); - } - } - return Collections.unmodifiableList(buildableLibraries); - } - - /* - * Rebuilds built libraries - * @return Number of libraries built as int, -1 & exception on error - */ - public int rebuildAllBuilt() throws RunnerException { - Collection builtLibraries = getBuiltLibraries(); - Library library; - Iterator libIterator = builtLibraries.iterator(); - int countBuilt = 0; - while(libIterator.hasNext()){ - library = (Library)libIterator.next(); - //System.out.println("Building library \"" + library.getName() + "\""); - try { - if(library.build()){ - ++countBuilt; - }else{ - return -1; - } - }catch (RunnerException re) { - throw new RunnerException(re.getMessage()); - } catch (Exception ex) { - throw new RunnerException(ex.toString()); - } - } - return countBuilt; - } - - /* - * Gathers paths to object files - * @return Array of strings of paths to object files - */ - public String[] getObjectFiles() { - ArrayList filesArrayList = new ArrayList(); - Collection builtLibraries = getBuiltLibraries(); - Library library; - File[] files; - Iterator libIterator = builtLibraries.iterator(); - while(libIterator.hasNext()){ - library = (Library)libIterator.next(); - files = library.getObjectFiles(); - for(int i = 0; i < files.length; ++i){ - filesArrayList.add(files[i].getPath()); - } - } - String[] filesArray = new String[filesArrayList.size()]; - filesArrayList.toArray(filesArray); - return filesArray; - } - - /* - * Gathers filenames of header files - * @return Array of strings of filenames of header files - */ - public String[] getHeaderFiles() { - ArrayList filesArrayList = new ArrayList(); - Collection builtLibraries = getBuiltLibraries(); - Library library; - File[] files; - Iterator libIterator = builtLibraries.iterator(); - while(libIterator.hasNext()){ - library = (Library)libIterator.next(); - files = library.getHeaderFiles(); - for(int i = 0; i < files.length; ++i){ - filesArrayList.add(files[i].getName()); - } - } - String[] filesArray = new String[filesArrayList.size()]; - filesArrayList.toArray(filesArray); - return filesArray; - } - - /* - * Gathers paths to library folders - * @return Array of strings of paths to library folders - */ - public String[] getFolderPaths() { - ArrayList foldersArrayList = new ArrayList(); - //Collection builtLibraries = getBuiltLibraries(); - Collection libraries = getAll(); - Library library; - //Iterator libIterator = builtLibraries.iterator(); - Iterator libIterator = libraries.iterator(); - while(libIterator.hasNext()){ - library = (Library)libIterator.next(); - foldersArrayList.add(library.getFolder().getPath()); - } - String[] foldersArray = new String[foldersArrayList.size()]; - foldersArrayList.toArray(foldersArray); - return foldersArray; - } - - /* - * Builds unbuilt libraries - * @return Number of libraries built as int, -1 & exception on error - */ - public int buildAllUnbuilt() throws RunnerException { - Collection buildableLibraries = getLibrariesToBuild(); - Library library; - Iterator libIterator = buildableLibraries.iterator(); - int countBuilt = 0; - while(libIterator.hasNext()){ - library = (Library)libIterator.next(); - //System.out.println("Building library \"" + library.getName() + "\""); - try { - if(library.build()){ - ++countBuilt; - }else{ - return -1; - } - }catch (RunnerException re) { - throw new RunnerException(re.getMessage()); - } catch (Exception ex) { - throw new RunnerException(ex.toString()); - } - } - return countBuilt; - } - - /* - * Populates examples menu with library folders - */ - public void populateExamplesMenu(JMenu examplesMenu, ActionListener listener) { - Library library; - Collection libraries = getBuiltLibraries(); - Iterator iterator = libraries.iterator(); - JMenu libraryExamples; - while(iterator.hasNext()){ - library = (Library)iterator.next(); - libraryExamples = library.getExamplesMenu(listener); - if(null != libraryExamples){ - examplesMenu.add(libraryExamples); - } - } - } - - /* - * Add syntax coloring - */ - public void addSyntaxColoring(PdeKeywords keywords) { - Library library; - Collection libraries = getBuiltLibraries(); - Iterator iterator = libraries.iterator(); - while(iterator.hasNext()){ - library = (Library)iterator.next(); - library.addSyntaxColors(keywords); - } - } -} diff --git a/app/src/processing/app/debug/Uploader.java b/app/src/processing/app/debug/Uploader.java new file mode 100755 index 000000000..624d58772 --- /dev/null +++ b/app/src/processing/app/debug/Uploader.java @@ -0,0 +1,220 @@ +/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Uploader - abstract uploading baseclass (common to both uisp and avrdude) + Part of the Arduino project - http://www.arduino.cc/ + + Copyright (c) 2004-05 + Hernando Barragan + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + $Id$ +*/ + +package processing.app.debug; + +import processing.app.Base; +import processing.app.Preferences; +import processing.app.Serial; + +import java.io.*; +import java.util.*; +import java.util.zip.*; +import javax.swing.*; +//#ifndef RXTX +//import javax.comm.*; +//#else +// rxtx uses package gnu.io, but all the class names +// are the same as those used by javax.comm +import gnu.io.*; +//#endif + + +public abstract class Uploader implements MessageConsumer { + static final String BUGS_URL = + "https://developer.berlios.de/bugs/?group_id=3590"; + static final String SUPER_BADNESS = + "Compiler error, please submit this code to " + BUGS_URL; + + RunnerException exception; + //PdePreferences preferences; + + //Serial serialPort; + static InputStream serialInput; + static OutputStream serialOutput; + //int serial; // last byte of data received + + public Uploader() { + } + + public abstract boolean uploadUsingPreferences(String buildPath, String className) + throws RunnerException; + + public abstract boolean burnBootloader(String programmer) throws RunnerException; + + protected void flushSerialBuffer() throws RunnerException { + // Cleanup the serial buffer + try { + Serial serialPort = new Serial(); + byte[] readBuffer; + while(serialPort.available() > 0) { + readBuffer = serialPort.readBytes(); + try { + Thread.sleep(100); + } catch (InterruptedException e) {} + } + + serialPort.setDTR(false); + + try { + Thread.sleep(100); + } catch (InterruptedException e) {} + + serialPort.setDTR(true); + + serialPort.dispose(); + } catch(Exception e) { + e.printStackTrace(); + throw new RunnerException(e.getMessage()); + } + } + + protected boolean executeUploadCommand(Collection commandDownloader) + throws RunnerException + { + firstErrorFound = false; // haven't found any errors yet + secondErrorFound = false; + notFoundError = false; + int result=0; // pre-initialized to quiet a bogus warning from jikes + + String userdir = System.getProperty("user.dir") + File.separator; + + try { + String[] commandArray = new String[commandDownloader.size()]; + commandDownloader.toArray(commandArray); + + String avrBasePath; + + if(Base.isLinux()) { + avrBasePath = new String(Base.getHardwarePath() + "/tools/"); + } + else { + avrBasePath = new String(Base.getHardwarePath() + "/tools/avr/bin/"); + } + + commandArray[0] = avrBasePath + commandArray[0]; + + if (Preferences.getBoolean("upload.verbose")) { + for(int i = 0; i < commandArray.length; i++) { + System.out.print(commandArray[i] + " "); + } + System.out.println(); + } + Process process = Runtime.getRuntime().exec(commandArray); + new MessageSiphon(process.getInputStream(), this); + new MessageSiphon(process.getErrorStream(), this); + + // wait for the process to finish. if interrupted + // before waitFor returns, continue waiting + // + boolean compiling = true; + while (compiling) { + try { + result = process.waitFor(); + compiling = false; + } catch (InterruptedException intExc) { + } + } + if(exception!=null) { + exception.hideStackTrace(); + throw exception; + } + if(result!=0) + return false; + } catch (Exception e) { + String msg = e.getMessage(); + if ((msg != null) && (msg.indexOf("uisp: not found") != -1) && (msg.indexOf("avrdude: not found") != -1)) { + //System.err.println("uisp is missing"); + //JOptionPane.showMessageDialog(editor.base, + // "Could not find the compiler.\n" + + // "uisp is missing from your PATH,\n" + + // "see readme.txt for help.", + // "Compiler error", + // JOptionPane.ERROR_MESSAGE); + return false; + } else { + e.printStackTrace(); + result = -1; + } + } + //System.out.println("result2 is "+result); + // if the result isn't a known, expected value it means that something + // is fairly wrong, one possibility is that jikes has crashed. + // + if (exception != null) throw exception; + + if ((result != 0) && (result != 1 )) { + exception = new RunnerException(SUPER_BADNESS); + //editor.error(exception); + //PdeBase.openURL(BUGS_URL); + //throw new PdeException(SUPER_BADNESS); + } + + return (result == 0); // ? true : false; + + } + + boolean firstErrorFound; + boolean secondErrorFound; + + // part of the PdeMessageConsumer interface + // + boolean notFoundError; + + public void message(String s) { + //System.err.println("MSG: " + s); + System.err.print(s); + + // ignore cautions + if (s.indexOf("Error") != -1) { + //exception = new RunnerException(s+" Check the serial port selected or your Board is connected"); + //System.out.println(s); + notFoundError = true; + return; + } + if(notFoundError) { + //System.out.println("throwing something"); + exception = new RunnerException("the selected serial port "+s+" does not exist or your board is not connected"); + return; + } + if (s.indexOf("Device is not responding") != -1 ) { + exception = new RunnerException("Device is not responding, check the right serial port is selected or RESET the board right before exporting"); + return; + } + if (s.indexOf("Programmer is not responding") != -1 || + s.indexOf("programmer is not responding") != -1 || + s.indexOf("protocol error") != -1) { + exception = new RunnerException("Problem uploading to board. See http://www.arduino.cc/en/Guide/Troubleshooting#upload for suggestions."); + return; + } + if (s.indexOf("Expected signature") != -1) { + exception = new RunnerException("Wrong microcontroller found. Did you select the right board from the Tools > Board menu?"); + return; + } + } + + +} diff --git a/build/macosx/dist/Processing.app/Contents/Info.plist b/build/macosx/dist/Processing.app/Contents/Info.plist index 75e85197c..c7ac50f8e 100755 --- a/build/macosx/dist/Processing.app/Contents/Info.plist +++ b/build/macosx/dist/Processing.app/Contents/Info.plist @@ -68,7 +68,7 @@ - $JAVAROOT/pde.jar:$JAVAROOT/core.jar:$JAVAROOT/antlr.jar:$JAVAROOT/ecj.jar:$JAVAROOT/registry.jar:$JAVAROOT/quaqua.jar:$JAVAROOT/oro.jar + $JAVAROOT/pde.jar:$JAVAROOT/core.jar:$JAVAROOT/antlr.jar:$JAVAROOT/ecj.jar:$JAVAROOT/registry.jar:$JAVAROOT/quaqua.jar:$JAVAROOT/oro.jar:$JAVAROOT/RXTXcomm.jar Properties diff --git a/build/macosx/make.sh b/build/macosx/make.sh index 2769f07fe..a22efbe79 100755 --- a/build/macosx/make.sh +++ b/build/macosx/make.sh @@ -34,6 +34,7 @@ else cp -X ../../app/lib/ecj.jar "$RESOURCES/" cp -X ../../app/lib/jna.jar "$RESOURCES/" cp -X ../../app/lib/oro.jar "$RESOURCES/" + cp -X ../../app/lib/RXTXcomm.jar "$RESOURCES/" echo Copying examples... cp -r ../shared/examples "$RESOURCES/" @@ -102,7 +103,7 @@ mkdir ../build/macosx/work/classes javac \ -Xlint:deprecation \ -source 1.5 -target 1.5 \ - -classpath "$RESOURCES/core.jar:$RESOURCES/antlr.jar:$RESOURCES/ecj.jar:$RESOURCES/jna.jar:$RESOURCES/oro.jar" \ + -classpath "$RESOURCES/core.jar:$RESOURCES/antlr.jar:$RESOURCES/ecj.jar:$RESOURCES/jna.jar:$RESOURCES/oro.jar:$RESOURCES/RXTXcomm.jar" \ -d ../build/macosx/work/classes \ src/processing/app/*.java \ src/processing/app/debug/*.java \