Initial Commit - Copy from Altus Metrum AltOS
This commit is contained in:
26
altosui/.gitignore
vendored
Normal file
26
altosui/.gitignore
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
windows/
|
||||
linux/
|
||||
macosx/
|
||||
fat/
|
||||
Manifest.txt
|
||||
Manifest-fat.txt
|
||||
AltosVersion.java
|
||||
Info.plist
|
||||
libaltosJNI
|
||||
classes
|
||||
altosui
|
||||
altosui-test
|
||||
altosui-jdb
|
||||
classaltosui.stamp
|
||||
altos-windows.nsi
|
||||
Altos-Linux-*.tar.bz2
|
||||
Altos-Linux-*.sh
|
||||
Altos-Mac-*.zip
|
||||
Altos-Windows-*.exe
|
||||
*.desktop
|
||||
*.dll
|
||||
*.dylib
|
||||
*.so
|
||||
*.jar
|
||||
*.class
|
||||
*.dmg
|
@@ -0,0 +1 @@
|
||||
<pkg-contents spec="1.12"><f n="AltosUI.app" o="keithp" g="keithp" p="16877" pt="/Users/keithp/altos/ao-tools/altosui/AltosUI.app" m="false" t="file"><f n="Contents" o="keithp" g="keithp" p="16877"><f n="Info.plist" o="keithp" g="keithp" p="33188"/><f n="MacOS" o="keithp" g="keithp" p="16877"><f n="JavaApplicationStub" o="keithp" g="keithp" p="33133"/></f><f n="PkgInfo" o="keithp" g="keithp" p="33188"/><f n="Resources" o="keithp" g="keithp" p="16877"><f n="AltosUIIcon.icns" o="keithp" g="keithp" p="33188"/><f n="Java" o="keithp" g="keithp" p="16877"/></f></f></f></pkg-contents>
|
1
altosui/AltOS Package Configuration.pmdoc/01altosui.xml
Normal file
1
altosui/AltOS Package Configuration.pmdoc/01altosui.xml
Normal file
@@ -0,0 +1 @@
|
||||
<pkgref spec="1.12" uuid="C5762664-2F26-4536-94C4-56F0FBC08D1A"><config><identifier>org.altusmetrum.altosUi.AltosUI.pkg</identifier><version>0.7</version><description></description><post-install type="none"/><installFrom relative="true" mod="true">AltosUI.app</installFrom><installTo mod="true" relocatable="true">/Applications/AltosUI.app</installTo><flags><followSymbolicLinks/></flags><packageStore type="internal"></packageStore><mod>installTo.path</mod><mod>installFrom.isRelativeType</mod><mod>version</mod><mod>parent</mod><mod>requireAuthorization</mod><mod>installTo</mod></config><contents><file-list>01altosui-contents.xml</file-list><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref>
|
1
altosui/AltOS Package Configuration.pmdoc/index.xml
Normal file
1
altosui/AltOS Package Configuration.pmdoc/index.xml
Normal file
@@ -0,0 +1 @@
|
||||
<pkmkdoc spec="1.12"><properties><title>AltOS UI</title><build>/Users/keithp/altos/ao-tools/altosui/AltosUI.pkg</build><organization>org.altusmetrum</organization><userSees ui="both"/><min-target os="3"/><domain system="true" user="true"/></properties><distribution><versions min-spec="1.000000"/><scripts></scripts></distribution><description>Install AltOS User Interface</description><contents><choice title="AltosUI" id="choice0" starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id="org.altusmetrum.altosUi.AltosUI.pkg"/></choice></contents><resources bg-scale="tofit" bg-align="center"><locale lang="en"><resource relative="true" mod="true" type="background">altusmetrum.jpg</resource></locale></resources><flags/><item type="file">01altosui.xml</item><mod>properties.anywhereDomain</mod><mod>properties.title</mod><mod>properties.customizeOption</mod><mod>description</mod><mod>properties.userDomain</mod><mod>properties.systemDomain</mod></pkmkdoc>
|
29
altosui/Altos.java
Normal file
29
altosui/Altos.java
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright © 2010 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.awt.*;
|
||||
import libaltosJNI.*;
|
||||
|
||||
import org.altusmetrum.altoslib_14.*;
|
||||
import org.altusmetrum.altosuilib_14.*;
|
||||
|
||||
public class Altos extends AltosUILib {
|
||||
|
||||
}
|
195
altosui/AltosAscent.java
Normal file
195
altosui/AltosAscent.java
Normal file
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright © 2010 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.util.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import org.altusmetrum.altoslib_14.*;
|
||||
import org.altusmetrum.altosuilib_14.*;
|
||||
|
||||
public class AltosAscent extends AltosUIFlightTab {
|
||||
JLabel cur, max;
|
||||
|
||||
class Height extends AltosUIUnitsIndicator {
|
||||
|
||||
public double value(AltosState state, int i) {
|
||||
if (i == 0)
|
||||
return state.height();
|
||||
else
|
||||
return state.max_height();
|
||||
}
|
||||
|
||||
public Height(Container container, int y) {
|
||||
super(container, y, AltosConvert.height, "Height", 2, false, 1);
|
||||
}
|
||||
}
|
||||
|
||||
class Speed extends AltosUIUnitsIndicator {
|
||||
public double value(AltosState state, int i) {
|
||||
if (i == 0)
|
||||
return state.speed();
|
||||
else
|
||||
return state.max_speed();
|
||||
}
|
||||
|
||||
public Speed(Container container, int y) {
|
||||
super(container, y, AltosConvert.speed, "Speed", 2, false, 1);
|
||||
}
|
||||
}
|
||||
|
||||
class Accel extends AltosUIUnitsIndicator {
|
||||
public boolean hide(double v) { return v == AltosLib.MISSING; }
|
||||
|
||||
public double value(AltosState state, int i) {
|
||||
if (i == 0)
|
||||
return state.acceleration();
|
||||
else
|
||||
return state.max_acceleration();
|
||||
}
|
||||
|
||||
public Accel(Container container, int y) {
|
||||
super(container, y, AltosConvert.accel, "Acceleration", 2, false, 1);
|
||||
}
|
||||
}
|
||||
|
||||
class Orient extends AltosUIUnitsIndicator {
|
||||
|
||||
public boolean hide(double v) { return v == AltosLib.MISSING; }
|
||||
|
||||
public double value(AltosState state, int i) {
|
||||
if (i == 0)
|
||||
return state.orient();
|
||||
else
|
||||
return state.max_orient();
|
||||
}
|
||||
|
||||
public Orient(Container container, int y) {
|
||||
super(container, y, AltosConvert.orient, "Tilt Angle", 2, false, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Apogee extends AltosUIUnitsIndicator {
|
||||
|
||||
public double value(AltosState state, int i) {
|
||||
return state.apogee_voltage;
|
||||
}
|
||||
|
||||
public boolean good(double v) { return v >= AltosLib.ao_igniter_good; }
|
||||
public boolean hide(double v) { return v == AltosLib.MISSING; }
|
||||
|
||||
public Apogee (Container container, int y) {
|
||||
super(container, y, AltosConvert.voltage, "Apogee Igniter Voltage", 1, true, 2);
|
||||
}
|
||||
}
|
||||
|
||||
class Main extends AltosUIUnitsIndicator {
|
||||
public double value(AltosState state, int i) {
|
||||
return state.main_voltage;
|
||||
}
|
||||
|
||||
public boolean good(double v) { return v >= AltosLib.ao_igniter_good; }
|
||||
public boolean hide(double v) { return v == AltosLib.MISSING; }
|
||||
|
||||
public Main (Container container, int y) {
|
||||
super(container, y, AltosConvert.voltage, "Main Igniter Voltage", 1, true, 2);
|
||||
}
|
||||
}
|
||||
|
||||
class Lat extends AltosUIUnitsIndicator {
|
||||
|
||||
public boolean hide(AltosState state, int i) {
|
||||
return state.gps == null || !state.gps.connected;
|
||||
}
|
||||
|
||||
public double value(AltosState state, int i) {
|
||||
if (state.gps == null)
|
||||
return AltosLib.MISSING;
|
||||
if (!state.gps.connected)
|
||||
return AltosLib.MISSING;
|
||||
return state.gps.lat;
|
||||
}
|
||||
|
||||
Lat (Container container, int y) {
|
||||
super (container, y, AltosConvert.latitude, "Latitude", 1, false, 2);
|
||||
}
|
||||
}
|
||||
|
||||
class Lon extends AltosUIUnitsIndicator {
|
||||
|
||||
public boolean hide(AltosState state, int i) {
|
||||
return state.gps == null || !state.gps.connected;
|
||||
}
|
||||
|
||||
public double value(AltosState state, int i) {
|
||||
if (state.gps == null)
|
||||
return AltosLib.MISSING;
|
||||
if (!state.gps.connected)
|
||||
return AltosLib.MISSING;
|
||||
return state.gps.lon;
|
||||
}
|
||||
|
||||
Lon (Container container, int y) {
|
||||
super (container, y, AltosConvert.longitude, "Longitude", 1, false, 2);
|
||||
}
|
||||
}
|
||||
|
||||
public void font_size_changed(int font_size) {
|
||||
super.font_size_changed(font_size);
|
||||
cur.setFont(AltosUILib.label_font);
|
||||
max.setFont(AltosUILib.label_font);
|
||||
}
|
||||
|
||||
public void labels(GridBagLayout layout, int y) {
|
||||
GridBagConstraints c;
|
||||
|
||||
cur = new JLabel("Current");
|
||||
cur.setFont(AltosUILib.label_font);
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = 2; c.gridy = y;
|
||||
c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
|
||||
layout.setConstraints(cur, c);
|
||||
add(cur);
|
||||
|
||||
max = new JLabel("Maximum");
|
||||
max.setFont(AltosUILib.label_font);
|
||||
c.gridx = 3; c.gridy = y;
|
||||
layout.setConstraints(max, c);
|
||||
add(max);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "Ascent";
|
||||
}
|
||||
|
||||
public AltosAscent() {
|
||||
int y = 0;
|
||||
labels(layout, y++);
|
||||
add(new Height(this, y++));
|
||||
add(new Speed(this, y++));
|
||||
add(new Accel(this, y++));
|
||||
add(new Orient(this, y++));
|
||||
add(new Lat(this, y++));
|
||||
add(new Lon(this, y++));
|
||||
add(new Apogee(this, y++));
|
||||
add(new Main(this, y++));
|
||||
}
|
||||
}
|
37
altosui/AltosChannelMenu.java
Normal file
37
altosui/AltosChannelMenu.java
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright © 2010 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
|
||||
public class AltosChannelMenu extends JComboBox<String> implements ActionListener {
|
||||
int channel;
|
||||
|
||||
public AltosChannelMenu(int current_channel) {
|
||||
|
||||
channel = current_channel;
|
||||
|
||||
for (int c = 0; c <= 9; c++)
|
||||
addItem(String.format("Channel %1d (%7.3fMHz)", c, 434.550 + c * 0.1));
|
||||
setSelectedIndex(channel);
|
||||
setMaximumRowCount(10);
|
||||
}
|
||||
|
||||
}
|
112
altosui/AltosCompanionInfo.java
Normal file
112
altosui/AltosCompanionInfo.java
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright © 2010 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.awt.*;
|
||||
import javax.swing.*;
|
||||
import org.altusmetrum.altoslib_14.*;
|
||||
import org.altusmetrum.altosuilib_14.*;
|
||||
|
||||
public class AltosCompanionInfo extends JTable implements AltosFlightDisplay {
|
||||
private AltosFlightInfoTableModel model;
|
||||
|
||||
static final int info_columns = 2;
|
||||
static final int info_rows = 17;
|
||||
|
||||
int desired_row_height() {
|
||||
FontMetrics infoValueMetrics = getFontMetrics(Altos.table_value_font);
|
||||
return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 18 / 10;
|
||||
}
|
||||
|
||||
public void font_size_changed(int font_size) {
|
||||
setFont(Altos.table_value_font);
|
||||
setRowHeight(desired_row_height());
|
||||
doLayout();
|
||||
}
|
||||
|
||||
public void units_changed(boolean imperial_units) {
|
||||
}
|
||||
|
||||
public AltosCompanionInfo() {
|
||||
super(new AltosFlightInfoTableModel(info_rows, info_columns));
|
||||
model = (AltosFlightInfoTableModel) getModel();
|
||||
setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS);
|
||||
setShowGrid(true);
|
||||
font_size_changed(AltosUIPreferences.font_size());
|
||||
}
|
||||
|
||||
public Dimension getPreferredScrollableViewportSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
model.reset();
|
||||
}
|
||||
|
||||
void info_add_row(int col, String name, String value) {
|
||||
model.addRow(col, name, value);
|
||||
}
|
||||
|
||||
void info_add_row(int col, String name, String format, Object... parameters) {
|
||||
info_add_row (col, name, String.format(format, parameters));
|
||||
}
|
||||
|
||||
void info_finish() {
|
||||
model.finish();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
model.clear();
|
||||
}
|
||||
|
||||
AltosCompanion companion;
|
||||
|
||||
public String board_name() {
|
||||
if (companion == null)
|
||||
return "None";
|
||||
switch (companion.board_id) {
|
||||
case AltosCompanion.board_id_telescience:
|
||||
return "TeleScience";
|
||||
default:
|
||||
return String.format("%02x\n", companion.board_id);
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() { return "Companion"; }
|
||||
|
||||
public void show(AltosState state, AltosListenerState listener_state) {
|
||||
if (state == null)
|
||||
return;
|
||||
if (state.companion != null)
|
||||
companion = state.companion;
|
||||
reset();
|
||||
info_add_row(0, "Companion board", "%s", board_name());
|
||||
if (companion != null) {
|
||||
info_add_row(0, "Last Data", "%5d", companion.tick);
|
||||
info_add_row(0, "Update period", "%5.2f s",
|
||||
companion.update_period / 100.0);
|
||||
info_add_row(0, "Channels", "%3d", companion.channels);
|
||||
|
||||
for (int i = 0; i < companion.channels; i++)
|
||||
info_add_row(1, String.format("Channel %2d", i),
|
||||
"%6d", companion.companion_data[i]);
|
||||
}
|
||||
info_finish();
|
||||
}
|
||||
}
|
317
altosui/AltosConfigFC.java
Normal file
317
altosui/AltosConfigFC.java
Normal file
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* Copyright © 2010 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import java.io.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.text.*;
|
||||
import org.altusmetrum.altoslib_14.*;
|
||||
import org.altusmetrum.altosuilib_14.*;
|
||||
|
||||
public class AltosConfigFC implements ActionListener {
|
||||
|
||||
class int_ref {
|
||||
int value;
|
||||
|
||||
public int get() {
|
||||
return value;
|
||||
}
|
||||
public void set(int i) {
|
||||
value = i;
|
||||
}
|
||||
public int_ref(int i) {
|
||||
value = i;
|
||||
}
|
||||
}
|
||||
|
||||
class string_ref {
|
||||
String value;
|
||||
|
||||
public String get() {
|
||||
return value;
|
||||
}
|
||||
public void set(String i) {
|
||||
value = i;
|
||||
}
|
||||
public string_ref(String i) {
|
||||
value = i;
|
||||
}
|
||||
}
|
||||
|
||||
JFrame owner;
|
||||
AltosDevice device;
|
||||
AltosSerial serial_line;
|
||||
boolean remote;
|
||||
|
||||
AltosConfigData data;
|
||||
AltosConfigFCUI config_ui;
|
||||
boolean serial_started;
|
||||
boolean made_visible;
|
||||
|
||||
void start_serial() throws InterruptedException, TimeoutException {
|
||||
serial_started = true;
|
||||
if (remote)
|
||||
serial_line.start_remote();
|
||||
}
|
||||
|
||||
void stop_serial() throws InterruptedException {
|
||||
if (!serial_started)
|
||||
return;
|
||||
serial_started = false;
|
||||
if (remote)
|
||||
serial_line.stop_remote();
|
||||
}
|
||||
|
||||
void update_ui() {
|
||||
data.set_values(config_ui);
|
||||
config_ui.set_clean();
|
||||
if (!made_visible) {
|
||||
made_visible = true;
|
||||
config_ui.make_visible();
|
||||
}
|
||||
}
|
||||
|
||||
int pyro;
|
||||
|
||||
final static int serial_mode_read = 0;
|
||||
final static int serial_mode_save = 1;
|
||||
final static int serial_mode_reboot = 2;
|
||||
|
||||
class SerialData implements Runnable {
|
||||
AltosConfigFC config;
|
||||
int serial_mode;
|
||||
|
||||
void callback(String in_cmd) {
|
||||
final String cmd = in_cmd;
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
if (cmd.equals("abort")) {
|
||||
abort();
|
||||
} else if (cmd.equals("all finished")) {
|
||||
if (serial_line != null)
|
||||
update_ui();
|
||||
}
|
||||
}
|
||||
};
|
||||
SwingUtilities.invokeLater(r);
|
||||
}
|
||||
|
||||
void get_data() {
|
||||
data = null;
|
||||
try {
|
||||
start_serial();
|
||||
data = new AltosConfigData(config.serial_line);
|
||||
} catch (InterruptedException ie) {
|
||||
} catch (TimeoutException te) {
|
||||
try {
|
||||
stop_serial();
|
||||
callback("abort");
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
stop_serial();
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
}
|
||||
callback("all finished");
|
||||
}
|
||||
|
||||
void save_data() {
|
||||
try {
|
||||
start_serial();
|
||||
data.save(serial_line, remote);
|
||||
if (remote)
|
||||
AltosUIPreferences.set_frequency(device.getSerial(),
|
||||
data.frequency());
|
||||
} catch (InterruptedException ie) {
|
||||
} catch (TimeoutException te) {
|
||||
} finally {
|
||||
try {
|
||||
stop_serial();
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void reboot() {
|
||||
try {
|
||||
start_serial();
|
||||
serial_line.printf("r eboot\n");
|
||||
serial_line.flush_output();
|
||||
} catch (InterruptedException ie) {
|
||||
} catch (TimeoutException te) {
|
||||
} finally {
|
||||
try {
|
||||
stop_serial();
|
||||
serial_line.close();
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void run () {
|
||||
switch (serial_mode) {
|
||||
case serial_mode_save:
|
||||
save_data();
|
||||
/* fall through ... */
|
||||
case serial_mode_read:
|
||||
get_data();
|
||||
break;
|
||||
case serial_mode_reboot:
|
||||
reboot();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public SerialData(AltosConfigFC in_config, int in_serial_mode) {
|
||||
config = in_config;
|
||||
serial_mode = in_serial_mode;
|
||||
}
|
||||
}
|
||||
|
||||
void run_serial_thread(int serial_mode) {
|
||||
SerialData sd = new SerialData(this, serial_mode);
|
||||
Thread st = new Thread(sd);
|
||||
st.start();
|
||||
}
|
||||
|
||||
void init_ui () throws InterruptedException, TimeoutException {
|
||||
config_ui = new AltosConfigFCUI(owner, remote);
|
||||
config_ui.addActionListener(this);
|
||||
serial_line.set_frame(owner);
|
||||
set_ui();
|
||||
}
|
||||
|
||||
void abort() {
|
||||
if (serial_line != null) {
|
||||
serial_line.close();
|
||||
serial_line = null;
|
||||
}
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
String.format("Connection to \"%s\" failed",
|
||||
device.toShortString()),
|
||||
"Connection Failed",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
config_ui.setVisible(false);
|
||||
}
|
||||
|
||||
void set_ui() throws InterruptedException, TimeoutException {
|
||||
if (serial_line != null)
|
||||
run_serial_thread(serial_mode_read);
|
||||
else
|
||||
update_ui();
|
||||
}
|
||||
|
||||
double frequency() {
|
||||
return AltosConvert.radio_to_frequency(data.radio_frequency,
|
||||
data.radio_setting,
|
||||
data.radio_calibration,
|
||||
data.radio_channel);
|
||||
}
|
||||
|
||||
void save_data() {
|
||||
|
||||
try {
|
||||
/* bounds check stuff */
|
||||
if (config_ui.flight_log_max() != AltosLib.MISSING &&
|
||||
config_ui.flight_log_max() > data.log_space() / 1024)
|
||||
{
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
String.format("Requested flight log, %dk, is larger than the available space, %dk.\n",
|
||||
config_ui.flight_log_max(),
|
||||
data.log_space() / 1024),
|
||||
"Maximum Flight Log Too Large",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Pull data out of the UI and stuff back into our local data record */
|
||||
|
||||
data.get_values(config_ui);
|
||||
run_serial_thread(serial_mode_save);
|
||||
} catch (AltosConfigDataException ae) {
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
ae.getMessage(),
|
||||
"Configuration Data Error",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String cmd = e.getActionCommand();
|
||||
try {
|
||||
if (cmd.equals("Save")) {
|
||||
save_data();
|
||||
} else if (cmd.equals("Reset")) {
|
||||
set_ui();
|
||||
} else if (cmd.equals("Reboot")) {
|
||||
if (serial_line != null)
|
||||
run_serial_thread(serial_mode_reboot);
|
||||
} else if (cmd.equals("Close")) {
|
||||
if (serial_line != null)
|
||||
serial_line.close();
|
||||
}
|
||||
else if (cmd.equals("Accel")) {
|
||||
if (data.pad_orientation != AltosLib.MISSING) {
|
||||
AltosUIAccelCal accel_ui = new AltosUIAccelCal(owner, serial_line, config_ui);
|
||||
if (accel_ui != null)
|
||||
accel_ui.doit();
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException ie) {
|
||||
abort();
|
||||
} catch (TimeoutException te) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
public AltosConfigFC(JFrame given_owner) {
|
||||
owner = given_owner;
|
||||
|
||||
device = AltosDeviceUIDialog.show(owner, Altos.product_any);
|
||||
if (device != null) {
|
||||
try {
|
||||
serial_line = new AltosSerial(device);
|
||||
try {
|
||||
if (device.matchProduct(Altos.product_basestation))
|
||||
remote = true;
|
||||
init_ui();
|
||||
} catch (InterruptedException ie) {
|
||||
abort();
|
||||
} catch (TimeoutException te) {
|
||||
abort();
|
||||
}
|
||||
} catch (FileNotFoundException ee) {
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
ee.getMessage(),
|
||||
"Cannot open target device",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} catch (AltosSerialInUseException si) {
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
String.format("Device \"%s\" already in use",
|
||||
device.toShortString()),
|
||||
"Device in use",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1777
altosui/AltosConfigFCUI.java
Normal file
1777
altosui/AltosConfigFCUI.java
Normal file
File diff suppressed because it is too large
Load Diff
477
altosui/AltosConfigPyroUI.java
Normal file
477
altosui/AltosConfigPyroUI.java
Normal file
@@ -0,0 +1,477 @@
|
||||
/*
|
||||
* Copyright © 2012 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.text.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
import org.altusmetrum.altoslib_14.*;
|
||||
import org.altusmetrum.altosuilib_14.*;
|
||||
|
||||
public class AltosConfigPyroUI
|
||||
extends AltosUIDialog
|
||||
implements ItemListener, DocumentListener, AltosUnitsListener, ActionListener
|
||||
{
|
||||
AltosConfigFCUI owner;
|
||||
Container pane;
|
||||
|
||||
static Insets il = new Insets(4,4,4,4);
|
||||
static Insets ir = new Insets(4,4,4,4);
|
||||
|
||||
static String[] state_names;
|
||||
|
||||
static void make_state_names() {
|
||||
if (state_names == null) {
|
||||
|
||||
state_names = new String[AltosLib.ao_flight_landed - AltosLib.ao_flight_boost + 1];
|
||||
for (int state = AltosLib.ao_flight_boost; state <= AltosLib.ao_flight_landed; state++)
|
||||
state_names[state - AltosLib.ao_flight_boost] = AltosLib.state_name_capital(state);
|
||||
}
|
||||
}
|
||||
|
||||
class PyroItem implements ItemListener, DocumentListener, AltosUnitsListener
|
||||
{
|
||||
public int flag;
|
||||
public JCheckBox enable;
|
||||
public JTextField value;
|
||||
public JComboBox<String> combo;
|
||||
AltosConfigPyroUI ui;
|
||||
boolean setting;
|
||||
|
||||
public void set_enable(boolean enable) {
|
||||
if (value != null)
|
||||
value.setEnabled(enable);
|
||||
if (combo != null)
|
||||
combo.setEnabled(enable);
|
||||
}
|
||||
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
set_enable(enable.isSelected());
|
||||
if (!setting)
|
||||
ui.set_dirty();
|
||||
}
|
||||
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
if (!setting)
|
||||
ui.set_dirty();
|
||||
}
|
||||
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
if (!setting)
|
||||
ui.set_dirty();
|
||||
}
|
||||
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
if (!setting)
|
||||
ui.set_dirty();
|
||||
}
|
||||
|
||||
public void units_changed(boolean imperial_units) {
|
||||
AltosUnits units = AltosPyro.pyro_to_units(flag);
|
||||
|
||||
if (units != null) {
|
||||
try {
|
||||
double v = units.parse_locale(value.getText(), !imperial_units);
|
||||
set(enabled(), v);
|
||||
} catch (ParseException pe) {
|
||||
set(enabled(), 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void set(boolean new_enable, double new_value) {
|
||||
setting = true;
|
||||
enable.setSelected(new_enable);
|
||||
set_enable(new_enable);
|
||||
if (value != null) {
|
||||
double scale = AltosPyro.pyro_to_scale(flag);
|
||||
double unit_value = new_value;
|
||||
AltosUnits units = AltosPyro.pyro_to_units(flag);
|
||||
if (units != null)
|
||||
unit_value = units.parse_value(new_value);
|
||||
String format;
|
||||
if (scale >= 100)
|
||||
format = "%6.2f";
|
||||
else if (scale >= 10)
|
||||
format = "%6.1f";
|
||||
else
|
||||
format = "%6.0f";
|
||||
value.setText(String.format(format, unit_value));
|
||||
}
|
||||
if (combo != null)
|
||||
if (new_value >= AltosLib.ao_flight_boost && new_value <= AltosLib.ao_flight_landed)
|
||||
combo.setSelectedIndex((int) new_value - AltosLib.ao_flight_boost);
|
||||
setting = false;
|
||||
}
|
||||
|
||||
public boolean enabled() {
|
||||
return enable.isSelected();
|
||||
}
|
||||
|
||||
public double value() throws AltosConfigDataException {
|
||||
if (value != null) {
|
||||
AltosUnits units = AltosPyro.pyro_to_units(flag);
|
||||
try {
|
||||
if (units != null)
|
||||
return units.parse_locale(value.getText());
|
||||
return AltosParse.parse_double_locale(value.getText());
|
||||
} catch (ParseException e) {
|
||||
throw new AltosConfigDataException("\"%s\": %s\n", value.getText(), e.getMessage());
|
||||
}
|
||||
}
|
||||
if (combo != null)
|
||||
return combo.getSelectedIndex() + AltosLib.ao_flight_boost;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public PyroItem(AltosConfigPyroUI in_ui, int in_flag, int x, int y) {
|
||||
|
||||
ui = in_ui;
|
||||
flag = in_flag;
|
||||
|
||||
GridBagConstraints c;
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = x; c.gridy = y;
|
||||
c.gridwidth = 1;
|
||||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.LINE_START;
|
||||
c.insets = il;
|
||||
enable = new JCheckBox();
|
||||
enable.addItemListener(this);
|
||||
pane.add(enable, c);
|
||||
|
||||
if ((flag & AltosPyro.pyro_no_value) == 0) {
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = x+1; c.gridy = y;
|
||||
c.gridwidth = 1;
|
||||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.LINE_START;
|
||||
c.insets = il;
|
||||
if ((flag & AltosPyro.pyro_state_value) != 0) {
|
||||
make_state_names();
|
||||
combo = new JComboBox<String>(state_names);
|
||||
combo.addItemListener(this);
|
||||
pane.add(combo, c);
|
||||
} else {
|
||||
value = new JTextField(10);
|
||||
value.getDocument().addDocumentListener(this);
|
||||
pane.add(value, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PyroColumn implements AltosUnitsListener {
|
||||
public PyroItem[] items;
|
||||
public JLabel label;
|
||||
int channel;
|
||||
|
||||
public void set(AltosPyro pyro) {
|
||||
int row = 0;
|
||||
if ((pyro.flags & AltosPyro.pyro_deprecate) != 0) {
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
String.format("Pyro settings “Ascending” and “Descending” are deprecated.\n" +
|
||||
"Clearing %s configuration.", AltosLib.igniter_name(pyro.channel)),
|
||||
"Deprecated Pyro Settings",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
pyro.flags = 0;
|
||||
owner.set_dirty();
|
||||
}
|
||||
for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
|
||||
if ((AltosPyro.pyro_all_useful & flag) != 0) {
|
||||
items[row].set((pyro.flags & flag) != 0,
|
||||
pyro.get_value(flag));
|
||||
row++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AltosPyro get() throws AltosConfigDataException {
|
||||
AltosPyro p = new AltosPyro(channel);
|
||||
|
||||
int row = 0;
|
||||
for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
|
||||
if ((AltosPyro.pyro_all_useful & flag) != 0) {
|
||||
if (items[row].enabled()) {
|
||||
try {
|
||||
p.flags |= flag;
|
||||
p.set_value(flag, items[row].value());
|
||||
} catch (AltosConfigDataException ae) {
|
||||
throw new AltosConfigDataException("%s, %s",
|
||||
AltosPyro.pyro_to_name(flag),
|
||||
ae.getMessage());
|
||||
}
|
||||
}
|
||||
row++;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
public void units_changed(boolean imperial_units) {
|
||||
int row = 0;
|
||||
for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
|
||||
if ((AltosPyro.pyro_all_useful & flag) != 0) {
|
||||
items[row].units_changed(imperial_units);
|
||||
row++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PyroColumn(AltosConfigPyroUI ui, int x, int y, int in_channel) {
|
||||
|
||||
channel = in_channel;
|
||||
|
||||
int nrow = 0;
|
||||
for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1)
|
||||
if ((flag & AltosPyro.pyro_all_useful) != 0)
|
||||
nrow++;
|
||||
|
||||
items = new PyroItem[nrow];
|
||||
int row = 0;
|
||||
|
||||
GridBagConstraints c;
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = x; c.gridy = y;
|
||||
c.gridwidth = 2;
|
||||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.CENTER;
|
||||
c.insets = il;
|
||||
label = new JLabel(String.format("Pyro Channel %c", 'A' + channel));
|
||||
pane.add(label, c);
|
||||
y++;
|
||||
|
||||
for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1)
|
||||
if ((flag & AltosPyro.pyro_all_useful) != 0) {
|
||||
items[row] = new PyroItem(ui, flag, x, y + row);
|
||||
row++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PyroColumn[] columns;
|
||||
JLabel[] labels;
|
||||
|
||||
public void set_pyros(AltosPyro[] pyros) {
|
||||
for (int i = 0; i < pyros.length; i++) {
|
||||
if (pyros[i].channel < columns.length)
|
||||
columns[pyros[i].channel].set(pyros[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public AltosPyro[] get_pyros() throws AltosConfigDataException {
|
||||
AltosPyro[] pyros = new AltosPyro[columns.length];
|
||||
for (int c = 0; c < columns.length; c++) {
|
||||
try {
|
||||
pyros[c] = columns[c].get();
|
||||
} catch (AltosConfigDataException ae) {
|
||||
throw new AltosConfigDataException ("Channel %c, %s", c + 'A', ae.getMessage());
|
||||
}
|
||||
}
|
||||
return pyros;
|
||||
}
|
||||
|
||||
JLabel pyro_firing_time_label;
|
||||
JComboBox<String> pyro_firing_time_value;
|
||||
|
||||
static String[] pyro_firing_time_values = {
|
||||
"0.050", "0.100", "0.250", "0.500", "1.0", "2.0"
|
||||
};
|
||||
|
||||
boolean initializing;
|
||||
|
||||
public void set_pyro_firing_time(double new_pyro_firing_time) {
|
||||
initializing = true;
|
||||
pyro_firing_time_value.setSelectedItem(Double.toString(new_pyro_firing_time));
|
||||
pyro_firing_time_value.setEnabled(new_pyro_firing_time >= 0);
|
||||
initializing = false;
|
||||
}
|
||||
|
||||
public double get_pyro_firing_time() throws AltosConfigDataException {
|
||||
String v = pyro_firing_time_value.getSelectedItem().toString();
|
||||
|
||||
try {
|
||||
return AltosParse.parse_double_locale(v);
|
||||
} catch (ParseException e) {
|
||||
throw new AltosConfigDataException("Invalid pyro firing time \"%s\"", v);
|
||||
}
|
||||
}
|
||||
|
||||
public void set_dirty() {
|
||||
if (!initializing)
|
||||
owner.set_dirty();
|
||||
}
|
||||
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
if (!initializing)
|
||||
owner.set_dirty();
|
||||
}
|
||||
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
if (!initializing)
|
||||
owner.set_dirty();
|
||||
}
|
||||
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
if (!initializing)
|
||||
owner.set_dirty();
|
||||
}
|
||||
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
if (!initializing)
|
||||
owner.set_dirty();
|
||||
}
|
||||
|
||||
public void units_changed(boolean imperial_units) {
|
||||
for (int c = 0; c < columns.length; c++)
|
||||
columns[c].units_changed(imperial_units);
|
||||
int r = 0;
|
||||
for (int flag = 1; flag <= AltosPyro.pyro_all; flag <<= 1) {
|
||||
if ((flag & AltosPyro.pyro_all_useful) != 0) {
|
||||
String n = AltosPyro.pyro_to_name(flag);
|
||||
if (n != null) {
|
||||
labels[r].setText(n);
|
||||
r++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* A window listener to catch closing events and tell the config code */
|
||||
class ConfigListener extends WindowAdapter {
|
||||
AltosConfigPyroUI ui;
|
||||
AltosConfigFCUI owner;
|
||||
|
||||
public ConfigListener(AltosConfigPyroUI this_ui, AltosConfigFCUI this_owner) {
|
||||
ui = this_ui;
|
||||
owner = this_owner;
|
||||
}
|
||||
|
||||
public void windowClosing(WindowEvent e) {
|
||||
ui.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
/* Listen for events from our buttons */
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String cmd = e.getActionCommand();
|
||||
|
||||
if (cmd.equals("Close"))
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
public AltosConfigPyroUI(AltosConfigFCUI in_owner, AltosPyro[] pyros, double pyro_firing_time) {
|
||||
|
||||
super(in_owner, "Configure Pyro Channels", false);
|
||||
|
||||
owner = in_owner;
|
||||
|
||||
GridBagConstraints c;
|
||||
|
||||
pane = getScrollablePane();
|
||||
pane.setLayout(new GridBagLayout());
|
||||
|
||||
int nrow = 0;
|
||||
for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1)
|
||||
if ((flag & AltosPyro.pyro_all_useful) != 0)
|
||||
nrow++;
|
||||
|
||||
labels = new JLabel[nrow];
|
||||
|
||||
int row = 1;
|
||||
|
||||
for (int flag = 1; flag <= AltosPyro.pyro_all; flag <<= 1) {
|
||||
String n;
|
||||
|
||||
if ((flag & AltosPyro.pyro_all_useful) != 0) {
|
||||
n = AltosPyro.pyro_to_name(flag);
|
||||
if (n != null) {
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = 0; c.gridy = row;
|
||||
c.gridwidth = 1;
|
||||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.LINE_START;
|
||||
c.insets = il;
|
||||
JLabel label = new JLabel(n);
|
||||
pane.add(label, c);
|
||||
labels[row-1] = label;
|
||||
row++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
columns = new PyroColumn[pyros.length];
|
||||
|
||||
for (int i = 0; i < pyros.length; i++) {
|
||||
columns[i] = new PyroColumn(this, i*2 + 1, 0, i);
|
||||
columns[i].set(pyros[i]);
|
||||
}
|
||||
|
||||
/* Pyro firing time */
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = 0; c.gridy = row;
|
||||
c.gridwidth = 2;
|
||||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.LINE_START;
|
||||
c.insets = il;
|
||||
c.ipady = 5;
|
||||
pyro_firing_time_label = new JLabel("Pyro Firing Time(s):");
|
||||
pane.add(pyro_firing_time_label, c);
|
||||
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = 2; c.gridy = row;
|
||||
c.gridwidth = 7;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.weightx = 1;
|
||||
c.anchor = GridBagConstraints.LINE_START;
|
||||
c.insets = ir;
|
||||
c.ipady = 5;
|
||||
pyro_firing_time_value = new JComboBox<String>(pyro_firing_time_values);
|
||||
pyro_firing_time_value.setEditable(true);
|
||||
pyro_firing_time_value.addItemListener(this);
|
||||
set_pyro_firing_time(pyro_firing_time);
|
||||
pane.add(pyro_firing_time_value, c);
|
||||
pyro_firing_time_value.setToolTipText("Length of extra pyro channel firing pulse");
|
||||
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = pyros.length*2-1;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.gridwidth = 2;
|
||||
c.gridy = 1000;
|
||||
JButton close = new JButton("Close");
|
||||
pane.add(close, c);
|
||||
close.addActionListener(this);
|
||||
close.setActionCommand("Close");
|
||||
|
||||
addWindowListener(new ConfigListener(this, owner));
|
||||
AltosPreferences.register_units_listener(this);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
AltosPreferences.unregister_units_listener(this);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public void make_visible() {
|
||||
pack();
|
||||
setVisible(true);
|
||||
}
|
||||
}
|
380
altosui/AltosConfigTD.java
Normal file
380
altosui/AltosConfigTD.java
Normal file
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Copyright © 2010 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import java.io.*;
|
||||
import java.util.concurrent.*;
|
||||
import org.altusmetrum.altoslib_14.*;
|
||||
import org.altusmetrum.altosuilib_14.*;
|
||||
|
||||
public class AltosConfigTD implements ActionListener {
|
||||
|
||||
class int_ref {
|
||||
int value;
|
||||
|
||||
public int get() {
|
||||
return value;
|
||||
}
|
||||
public void set(int i) {
|
||||
value = i;
|
||||
}
|
||||
public int_ref(int i) {
|
||||
value = i;
|
||||
}
|
||||
}
|
||||
|
||||
class string_ref {
|
||||
String value;
|
||||
|
||||
public String get() {
|
||||
return value;
|
||||
}
|
||||
public void set(String i) {
|
||||
value = i;
|
||||
}
|
||||
public string_ref(String i) {
|
||||
value = i;
|
||||
}
|
||||
}
|
||||
|
||||
JFrame owner;
|
||||
AltosDevice device;
|
||||
AltosSerial serial_line;
|
||||
int_ref serial;
|
||||
int_ref radio_channel;
|
||||
int_ref radio_calibration;
|
||||
int_ref radio_setting;
|
||||
int_ref radio_frequency;
|
||||
int_ref telemetry_rate;
|
||||
string_ref config_version;
|
||||
string_ref version;
|
||||
string_ref product;
|
||||
AltosConfigTDUI config_ui;
|
||||
boolean made_visible;
|
||||
|
||||
boolean get_int(String line, String label, int_ref x) {
|
||||
if (line.startsWith(label)) {
|
||||
try {
|
||||
String tail = line.substring(label.length()).trim();
|
||||
String[] tokens = tail.split("\\s+");
|
||||
if (tokens.length > 0) {
|
||||
int i = Integer.parseInt(tokens[0]);
|
||||
x.set(i);
|
||||
return true;
|
||||
}
|
||||
} catch (NumberFormatException ne) {
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean get_string(String line, String label, string_ref s) {
|
||||
if (line.startsWith(label)) {
|
||||
String quoted = line.substring(label.length()).trim();
|
||||
|
||||
if (quoted.startsWith("\""))
|
||||
quoted = quoted.substring(1);
|
||||
if (quoted.endsWith("\""))
|
||||
quoted = quoted.substring(0,quoted.length()-1);
|
||||
s.set(quoted);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void update_ui() {
|
||||
config_ui.set_serial(serial.get());
|
||||
config_ui.set_product(product.get());
|
||||
config_ui.set_version(version.get());
|
||||
config_ui.set_radio_frequency(frequency());
|
||||
config_ui.set_radio_calibration(radio_calibration.get());
|
||||
config_ui.set_telemetry_rate(telemetry_rate.get());
|
||||
config_ui.set_clean();
|
||||
if (!made_visible) {
|
||||
made_visible = true;
|
||||
config_ui.make_visible();
|
||||
}
|
||||
}
|
||||
|
||||
void finish_input(String line) {
|
||||
if (line == null) {
|
||||
abort();
|
||||
return;
|
||||
}
|
||||
if (line.equals("all finished")) {
|
||||
if (serial_line != null)
|
||||
update_ui();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void process_line(String line) {
|
||||
if (line == null || line.equals("all finished")) {
|
||||
final String last_line = line;
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
finish_input(last_line);
|
||||
}
|
||||
};
|
||||
SwingUtilities.invokeLater(r);
|
||||
} else {
|
||||
get_string(line, "Config version", config_version);
|
||||
get_int(line, "serial-number", serial);
|
||||
get_int(line, "Radio channel:", radio_channel);
|
||||
get_int(line, "Radio cal:", radio_calibration);
|
||||
get_int(line, "Frequency:", radio_frequency);
|
||||
get_int(line, "Radio setting:", radio_setting);
|
||||
get_int(line, "Telemetry rate:", telemetry_rate);
|
||||
get_string(line,"software-version", version);
|
||||
get_string(line,"product", product);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void reset_data() {
|
||||
serial.set(0);
|
||||
radio_channel.set(0);
|
||||
radio_setting.set(0);
|
||||
radio_frequency.set(0);
|
||||
radio_calibration.set(1186611);
|
||||
telemetry_rate.set(Altos.ao_telemetry_rate_38400);
|
||||
config_version.set("0.0");
|
||||
version.set("unknown");
|
||||
product.set("unknown");
|
||||
}
|
||||
|
||||
synchronized double frequency() {
|
||||
return AltosConvert.radio_to_frequency(radio_frequency.get(),
|
||||
radio_setting.get(),
|
||||
radio_calibration.get(),
|
||||
radio_channel.get());
|
||||
}
|
||||
|
||||
synchronized void set_frequency(double freq) {
|
||||
int frequency = radio_frequency.get();
|
||||
int setting = radio_setting.get();
|
||||
|
||||
if (frequency > 0) {
|
||||
radio_frequency.set((int) Math.floor (freq * 1000 + 0.5));
|
||||
} else if (setting > 0) {
|
||||
radio_setting.set(AltosConvert.radio_frequency_to_setting(freq,
|
||||
radio_calibration.get()));
|
||||
radio_channel.set(0);
|
||||
} else {
|
||||
radio_channel.set(AltosConvert.radio_frequency_to_channel(freq));
|
||||
}
|
||||
}
|
||||
|
||||
synchronized int telemetry_rate() {
|
||||
return telemetry_rate.get();
|
||||
}
|
||||
|
||||
synchronized void set_telemetry_rate(int new_telemetry_rate){
|
||||
int rate = telemetry_rate.get();
|
||||
|
||||
if (rate >= 0)
|
||||
telemetry_rate.set(new_telemetry_rate);
|
||||
}
|
||||
|
||||
final static int serial_mode_read = 0;
|
||||
final static int serial_mode_save = 1;
|
||||
final static int serial_mode_reboot = 2;
|
||||
|
||||
SerialData serial_data;
|
||||
Thread serial_thread;
|
||||
|
||||
class SerialData implements Runnable {
|
||||
AltosConfigTD config;
|
||||
int serial_mode;
|
||||
|
||||
void get_data() {
|
||||
try {
|
||||
boolean been_there = false;
|
||||
config.reset_data();
|
||||
|
||||
while (config.serial_line != null) {
|
||||
config.serial_line.printf("c s\nf\nv\n");
|
||||
while (config.serial_line != null) {
|
||||
try {
|
||||
String line = config.serial_line.get_reply(5000);
|
||||
config.process_line(line);
|
||||
if (line != null && line.startsWith("software-version"))
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (been_there)
|
||||
break;
|
||||
if (!config_version.get().equals("0.0"))
|
||||
break;
|
||||
been_there = true;
|
||||
if (config != null && config.serial_line != null) {
|
||||
config.serial_line.printf("C\n ");
|
||||
config.serial_line.flush_input();
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
/*
|
||||
* This makes sure the displayed frequency respects the limits that the
|
||||
* available firmware version might place on the actual frequency
|
||||
*/
|
||||
config.set_frequency(AltosPreferences.frequency(serial.get()));
|
||||
config.set_telemetry_rate(AltosPreferences.telemetry_rate(serial.get()));
|
||||
config.process_line("all finished");
|
||||
}
|
||||
|
||||
void save_data() {
|
||||
double frequency = frequency();
|
||||
if (frequency != 0)
|
||||
AltosPreferences.set_frequency(serial.get(),
|
||||
frequency);
|
||||
AltosPreferences.set_telemetry_rate(serial.get(),
|
||||
telemetry_rate());
|
||||
}
|
||||
|
||||
public void run () {
|
||||
switch (serial_mode) {
|
||||
case serial_mode_save:
|
||||
save_data();
|
||||
/* fall through ... */
|
||||
case serial_mode_read:
|
||||
get_data();
|
||||
serial_thread = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public SerialData(AltosConfigTD in_config, int in_serial_mode) {
|
||||
config = in_config;
|
||||
serial_mode = in_serial_mode;
|
||||
}
|
||||
}
|
||||
|
||||
void run_serial_thread(int serial_mode) {
|
||||
serial_data = new SerialData(this, serial_mode);
|
||||
serial_thread = new Thread(serial_data);
|
||||
serial_thread.start();
|
||||
}
|
||||
|
||||
void abort_serial_thread() {
|
||||
if (serial_thread != null) {
|
||||
serial_thread.interrupt();
|
||||
serial_thread = null;
|
||||
}
|
||||
}
|
||||
void init_ui () throws InterruptedException, TimeoutException {
|
||||
config_ui = new AltosConfigTDUI(owner);
|
||||
config_ui.addActionListener(this);
|
||||
serial_line.set_frame(owner);
|
||||
set_ui();
|
||||
}
|
||||
|
||||
void abort() {
|
||||
abort_serial_thread();
|
||||
if (serial_line != null) {
|
||||
serial_line.close();
|
||||
serial_line = null;
|
||||
}
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
String.format("Connection to \"%s\" failed",
|
||||
device.toShortString()),
|
||||
"Connection Failed",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
config_ui.setVisible(false);
|
||||
}
|
||||
|
||||
void set_ui() throws InterruptedException, TimeoutException {
|
||||
if (serial_line != null)
|
||||
run_serial_thread(serial_mode_read);
|
||||
else
|
||||
update_ui();
|
||||
}
|
||||
|
||||
void save_data() {
|
||||
double freq = config_ui.radio_frequency();
|
||||
set_frequency(freq);
|
||||
int telemetry_rate = config_ui.telemetry_rate();
|
||||
set_telemetry_rate(telemetry_rate);
|
||||
run_serial_thread(serial_mode_save);
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String cmd = e.getActionCommand();
|
||||
try {
|
||||
if (cmd.equals("Save")) {
|
||||
save_data();
|
||||
} else if (cmd.equals("Reset")) {
|
||||
set_ui();
|
||||
} else if (cmd.equals("Reboot")) {
|
||||
if (serial_line != null)
|
||||
run_serial_thread(serial_mode_reboot);
|
||||
} else if (cmd.equals("Close")) {
|
||||
if (serial_line != null)
|
||||
serial_line.close();
|
||||
}
|
||||
} catch (InterruptedException ie) {
|
||||
abort();
|
||||
} catch (TimeoutException te) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
public AltosConfigTD(JFrame given_owner) {
|
||||
owner = given_owner;
|
||||
|
||||
serial = new int_ref(0);
|
||||
radio_channel = new int_ref(0);
|
||||
radio_setting = new int_ref(0);
|
||||
radio_frequency = new int_ref(0);
|
||||
radio_calibration = new int_ref(1186611);
|
||||
telemetry_rate = new int_ref(AltosLib.ao_telemetry_rate_38400);
|
||||
config_version = new string_ref("0.0");
|
||||
version = new string_ref("unknown");
|
||||
product = new string_ref("unknown");
|
||||
|
||||
device = AltosDeviceUIDialog.show(owner, Altos.product_basestation);
|
||||
if (device != null) {
|
||||
try {
|
||||
serial_line = new AltosSerial(device);
|
||||
try {
|
||||
init_ui();
|
||||
} catch (InterruptedException ie) {
|
||||
abort();
|
||||
} catch (TimeoutException te) {
|
||||
abort();
|
||||
}
|
||||
} catch (FileNotFoundException ee) {
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
ee.getMessage(),
|
||||
"Cannot open target device",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} catch (AltosSerialInUseException si) {
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
String.format("Device \"%s\" already in use",
|
||||
device.toShortString()),
|
||||
"Device in use",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
378
altosui/AltosConfigTDUI.java
Normal file
378
altosui/AltosConfigTDUI.java
Normal file
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
* Copyright © 2010 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
import org.altusmetrum.altoslib_14.*;
|
||||
import org.altusmetrum.altosuilib_14.*;
|
||||
|
||||
public class AltosConfigTDUI
|
||||
extends AltosUIDialog
|
||||
implements ActionListener, ItemListener, DocumentListener
|
||||
{
|
||||
|
||||
Container pane;
|
||||
Box box;
|
||||
JLabel product_label;
|
||||
JLabel version_label;
|
||||
JLabel serial_label;
|
||||
JLabel frequency_label;
|
||||
JLabel radio_calibration_label;
|
||||
JLabel radio_frequency_label;
|
||||
JLabel rate_label;
|
||||
|
||||
public boolean dirty;
|
||||
|
||||
JFrame owner;
|
||||
JLabel product_value;
|
||||
JLabel version_value;
|
||||
JLabel serial_value;
|
||||
AltosUIFreqList radio_frequency_value;
|
||||
JLabel radio_calibration_value;
|
||||
AltosUIRateList rate_value;
|
||||
|
||||
JButton save;
|
||||
JButton reset;
|
||||
JButton reboot;
|
||||
JButton close;
|
||||
|
||||
ActionListener listener;
|
||||
|
||||
/* A window listener to catch closing events and tell the config code */
|
||||
class ConfigListener extends WindowAdapter {
|
||||
AltosConfigTDUI ui;
|
||||
|
||||
public ConfigListener(AltosConfigTDUI this_ui) {
|
||||
ui = this_ui;
|
||||
}
|
||||
|
||||
public void windowClosing(WindowEvent e) {
|
||||
ui.actionPerformed(new ActionEvent(e.getSource(),
|
||||
ActionEvent.ACTION_PERFORMED,
|
||||
"Close"));
|
||||
}
|
||||
}
|
||||
|
||||
/* Build the UI using a grid bag */
|
||||
public AltosConfigTDUI(JFrame in_owner) {
|
||||
super (in_owner, "Configure TeleDongle", false);
|
||||
|
||||
owner = in_owner;
|
||||
GridBagConstraints c;
|
||||
|
||||
Insets il = new Insets(4,4,4,4);
|
||||
Insets ir = new Insets(4,4,4,4);
|
||||
|
||||
pane = getScrollablePane();
|
||||
pane.setLayout(new GridBagLayout());
|
||||
|
||||
/* Product */
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = 0; c.gridy = 0;
|
||||
c.gridwidth = 4;
|
||||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.LINE_START;
|
||||
c.insets = il;
|
||||
product_label = new JLabel("Product:");
|
||||
pane.add(product_label, c);
|
||||
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = 4; c.gridy = 0;
|
||||
c.gridwidth = 4;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.weightx = 1;
|
||||
c.anchor = GridBagConstraints.LINE_START;
|
||||
c.insets = ir;
|
||||
product_value = new JLabel("");
|
||||
pane.add(product_value, c);
|
||||
|
||||
/* Version */
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = 0; c.gridy = 1;
|
||||
c.gridwidth = 4;
|
||||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.LINE_START;
|
||||
c.insets = il;
|
||||
c.ipady = 5;
|
||||
version_label = new JLabel("Software version:");
|
||||
pane.add(version_label, c);
|
||||
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = 4; c.gridy = 1;
|
||||
c.gridwidth = 4;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.weightx = 1;
|
||||
c.anchor = GridBagConstraints.LINE_START;
|
||||
c.insets = ir;
|
||||
c.ipady = 5;
|
||||
version_value = new JLabel("");
|
||||
pane.add(version_value, c);
|
||||
|
||||
/* Serial */
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = 0; c.gridy = 2;
|
||||
c.gridwidth = 4;
|
||||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.LINE_START;
|
||||
c.insets = il;
|
||||
c.ipady = 5;
|
||||
serial_label = new JLabel("Serial:");
|
||||
pane.add(serial_label, c);
|
||||
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = 4; c.gridy = 2;
|
||||
c.gridwidth = 4;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.weightx = 1;
|
||||
c.anchor = GridBagConstraints.LINE_START;
|
||||
c.insets = ir;
|
||||
c.ipady = 5;
|
||||
serial_value = new JLabel("");
|
||||
pane.add(serial_value, c);
|
||||
|
||||
/* Frequency */
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = 0; c.gridy = 5;
|
||||
c.gridwidth = 4;
|
||||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.LINE_START;
|
||||
c.insets = il;
|
||||
c.ipady = 5;
|
||||
radio_frequency_label = new JLabel("Frequency:");
|
||||
pane.add(radio_frequency_label, c);
|
||||
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = 4; c.gridy = 5;
|
||||
c.gridwidth = 4;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.weightx = 1;
|
||||
c.anchor = GridBagConstraints.LINE_START;
|
||||
c.insets = ir;
|
||||
c.ipady = 5;
|
||||
radio_frequency_value = new AltosUIFreqList();
|
||||
radio_frequency_value.addItemListener(this);
|
||||
pane.add(radio_frequency_value, c);
|
||||
radio_frequency_value.setToolTipText("Telemetry, RDF and packet frequency");
|
||||
|
||||
/* Radio Calibration */
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = 0; c.gridy = 6;
|
||||
c.gridwidth = 4;
|
||||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.LINE_START;
|
||||
c.insets = il;
|
||||
c.ipady = 5;
|
||||
radio_calibration_label = new JLabel("RF Calibration:");
|
||||
pane.add(radio_calibration_label, c);
|
||||
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = 4; c.gridy = 6;
|
||||
c.gridwidth = 4;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.weightx = 1;
|
||||
c.anchor = GridBagConstraints.LINE_START;
|
||||
c.insets = ir;
|
||||
c.ipady = 5;
|
||||
radio_calibration_value = new JLabel(String.format("%d", 1186611));
|
||||
pane.add(radio_calibration_value, c);
|
||||
|
||||
/* Telemetry Rate */
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = 0; c.gridy = 7;
|
||||
c.gridwidth = 4;
|
||||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.LINE_START;
|
||||
c.insets = il;
|
||||
c.ipady = 5;
|
||||
rate_label = new JLabel("Telemetry Rate:");
|
||||
pane.add(rate_label, c);
|
||||
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = 4; c.gridy = 7;
|
||||
c.gridwidth = 4;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.weightx = 1;
|
||||
c.anchor = GridBagConstraints.LINE_START;
|
||||
c.insets = ir;
|
||||
c.ipady = 5;
|
||||
rate_value = new AltosUIRateList();
|
||||
pane.add(rate_value, c);
|
||||
|
||||
/* Buttons */
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = 0; c.gridy = 12;
|
||||
c.gridwidth = 2;
|
||||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.LINE_START;
|
||||
c.insets = il;
|
||||
save = new JButton("Save");
|
||||
pane.add(save, c);
|
||||
save.addActionListener(this);
|
||||
save.setActionCommand("Save");
|
||||
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = 2; c.gridy = 12;
|
||||
c.gridwidth = 2;
|
||||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.CENTER;
|
||||
c.insets = il;
|
||||
reset = new JButton("Reset");
|
||||
pane.add(reset, c);
|
||||
reset.addActionListener(this);
|
||||
reset.setActionCommand("Reset");
|
||||
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = 6; c.gridy = 12;
|
||||
c.gridwidth = 2;
|
||||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.LINE_END;
|
||||
c.insets = il;
|
||||
close = new JButton("Close");
|
||||
pane.add(close, c);
|
||||
close.addActionListener(this);
|
||||
close.setActionCommand("Close");
|
||||
|
||||
addWindowListener(new ConfigListener(this));
|
||||
}
|
||||
|
||||
/* Once the initial values are set, the config code will show the dialog */
|
||||
public void make_visible() {
|
||||
pack();
|
||||
setLocationRelativeTo(owner);
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
/* If any values have been changed, confirm before closing */
|
||||
public boolean check_dirty(String operation) {
|
||||
if (dirty) {
|
||||
Object[] options = { String.format("%s anyway", operation), "Keep editing" };
|
||||
int i;
|
||||
i = JOptionPane.showOptionDialog(this,
|
||||
String.format("Configuration modified. %s anyway?", operation),
|
||||
"Configuration Modified",
|
||||
JOptionPane.DEFAULT_OPTION,
|
||||
JOptionPane.WARNING_MESSAGE,
|
||||
null, options, options[1]);
|
||||
if (i != 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Listen for events from our buttons */
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String cmd = e.getActionCommand();
|
||||
|
||||
if (cmd.equals("Close") || cmd.equals("Reboot"))
|
||||
if (!check_dirty(cmd))
|
||||
return;
|
||||
listener.actionPerformed(e);
|
||||
if (cmd.equals("Close") || cmd.equals("Reboot")) {
|
||||
setVisible(false);
|
||||
dispose();
|
||||
}
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
/* ItemListener interface method */
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
/* DocumentListener interface methods */
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
/* Let the config code hook on a listener */
|
||||
public void addActionListener(ActionListener l) {
|
||||
listener = l;
|
||||
}
|
||||
|
||||
/* set and get all of the dialog values */
|
||||
public void set_product(String product) {
|
||||
radio_frequency_value.set_product(product);
|
||||
product_value.setText(product);
|
||||
}
|
||||
|
||||
public void set_version(String version) {
|
||||
version_value.setText(version);
|
||||
}
|
||||
|
||||
public void set_serial(int serial) {
|
||||
radio_frequency_value.set_serial(serial);
|
||||
serial_value.setText(String.format("%d", serial));
|
||||
}
|
||||
|
||||
public void set_radio_frequency(double new_radio_frequency) {
|
||||
int i;
|
||||
for (i = 0; i < radio_frequency_value.getItemCount(); i++) {
|
||||
AltosFrequency f = (AltosFrequency) radio_frequency_value.getItemAt(i);
|
||||
|
||||
if (f.close(new_radio_frequency)) {
|
||||
radio_frequency_value.setSelectedIndex(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < radio_frequency_value.getItemCount(); i++) {
|
||||
AltosFrequency f = (AltosFrequency) radio_frequency_value.getItemAt(i);
|
||||
|
||||
if (new_radio_frequency < f.frequency)
|
||||
break;
|
||||
}
|
||||
String description = String.format("%s serial %s",
|
||||
product_value.getText(),
|
||||
serial_value.getText());
|
||||
AltosFrequency new_frequency = new AltosFrequency(new_radio_frequency, description);
|
||||
AltosPreferences.add_common_frequency(new_frequency);
|
||||
radio_frequency_value.insertItemAt(new_frequency, i);
|
||||
radio_frequency_value.setSelectedIndex(i);
|
||||
}
|
||||
|
||||
public double radio_frequency() {
|
||||
return radio_frequency_value.frequency();
|
||||
}
|
||||
|
||||
public void set_radio_calibration(int calibration) {
|
||||
radio_calibration_value.setText(String.format("%d", calibration));
|
||||
}
|
||||
|
||||
public int telemetry_rate() {
|
||||
return rate_value.getSelectedIndex();
|
||||
}
|
||||
|
||||
public void set_telemetry_rate(int rate) {
|
||||
rate_value.setSelectedIndex(rate);
|
||||
}
|
||||
|
||||
public void set_clean() {
|
||||
dirty = false;
|
||||
}
|
||||
}
|
157
altosui/AltosConfigureUI.java
Normal file
157
altosui/AltosConfigureUI.java
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright © 2010 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.beans.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
import org.altusmetrum.altosuilib_14.*;
|
||||
|
||||
public class AltosConfigureUI
|
||||
extends AltosUIConfigure
|
||||
implements DocumentListener
|
||||
{
|
||||
AltosVoice voice;
|
||||
|
||||
public JTextField callsign_value;
|
||||
public JComboBox<String> position_value;
|
||||
|
||||
/* DocumentListener interface methods */
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
changedUpdate(e);
|
||||
}
|
||||
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
changedUpdate(e);
|
||||
}
|
||||
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
if (callsign_value != null)
|
||||
AltosUIPreferences.set_callsign(callsign_value.getText());
|
||||
}
|
||||
|
||||
public void add_voice() {
|
||||
|
||||
/* Voice settings */
|
||||
pane.add(new JLabel("Voice"), constraints(0, 1));
|
||||
|
||||
JRadioButton enable_voice = new JRadioButton("Enable", AltosUIPreferences.voice());
|
||||
enable_voice.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JRadioButton item = (JRadioButton) e.getSource();
|
||||
boolean enabled = item.isSelected();
|
||||
AltosUIPreferences.set_voice(enabled);
|
||||
if (enabled)
|
||||
voice.speak_always("Enable voice.");
|
||||
else
|
||||
voice.speak_always("Disable voice.");
|
||||
}
|
||||
});
|
||||
pane.add(enable_voice, constraints(1, 1));
|
||||
enable_voice.setToolTipText("Enable/Disable all audio in-flight announcements");
|
||||
|
||||
JButton test_voice = new JButton("Test Voice");
|
||||
test_voice.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
voice.speak("That's one small step for man; one giant leap for mankind.");
|
||||
}
|
||||
});
|
||||
pane.add(test_voice, constraints(2, 1));
|
||||
test_voice.setToolTipText("Play a stock audio clip to check volume");
|
||||
row++;
|
||||
}
|
||||
|
||||
public void add_callsign() {
|
||||
/* Callsign setting */
|
||||
pane.add(new JLabel("Callsign"), constraints(0, 1));
|
||||
|
||||
callsign_value = new JTextField(AltosUIPreferences.callsign());
|
||||
callsign_value.getDocument().addDocumentListener(this);
|
||||
callsign_value.setToolTipText("Callsign sent in packet mode");
|
||||
pane.add(callsign_value, constraints(1, 2, GridBagConstraints.BOTH));
|
||||
row++;
|
||||
}
|
||||
|
||||
boolean has_bluetooth;
|
||||
|
||||
public void add_bluetooth() {
|
||||
JButton manage_bluetooth = new JButton("Manage Bluetooth");
|
||||
manage_bluetooth.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
AltosBTManage.show(owner, AltosBTKnown.bt_known());
|
||||
}
|
||||
});
|
||||
pane.add(manage_bluetooth, constraints(0, 2));
|
||||
/* in the same row as add_frequencies, so don't bump row */
|
||||
has_bluetooth = true;
|
||||
}
|
||||
|
||||
public void add_frequencies() {
|
||||
JButton manage_frequencies = new JButton("Manage Frequencies");
|
||||
manage_frequencies.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
AltosConfigFreqUI.show(owner);
|
||||
}
|
||||
});
|
||||
manage_frequencies.setToolTipText("Configure which values are shown in frequency menus");
|
||||
if (has_bluetooth)
|
||||
pane.add(manage_frequencies, constraints(2, 1));
|
||||
else
|
||||
pane.add(manage_frequencies, constraints(0, 3));
|
||||
row++;
|
||||
}
|
||||
|
||||
final static String[] position_names = {
|
||||
"Top left",
|
||||
"Top",
|
||||
"Top right",
|
||||
"Left",
|
||||
"Center",
|
||||
"Right",
|
||||
"Bottom left",
|
||||
"Bottom",
|
||||
"Bottom right",
|
||||
};
|
||||
|
||||
public void add_position() {
|
||||
pane.add(new JLabel ("Menu position"), constraints(0, 1));
|
||||
|
||||
position_value = new JComboBox<String>(position_names);
|
||||
position_value.setMaximumRowCount(position_names.length);
|
||||
int position = AltosUIPreferences.position();
|
||||
position_value.setSelectedIndex(position);
|
||||
position_value.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int position = position_value.getSelectedIndex();
|
||||
AltosUIPreferences.set_position(position);
|
||||
}
|
||||
});
|
||||
pane.add(position_value, constraints(1, 2, GridBagConstraints.BOTH));
|
||||
position_value.setToolTipText("Position of main AltosUI window");
|
||||
row++;
|
||||
}
|
||||
|
||||
public AltosConfigureUI(JFrame owner, AltosVoice voice) {
|
||||
super(owner);
|
||||
|
||||
this.voice = voice;
|
||||
}
|
||||
}
|
165
altosui/AltosDescent.java
Normal file
165
altosui/AltosDescent.java
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright © 2010 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.util.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import org.altusmetrum.altoslib_14.*;
|
||||
import org.altusmetrum.altosuilib_14.*;
|
||||
|
||||
public class AltosDescent extends AltosUIFlightTab {
|
||||
|
||||
class Height extends AltosUIUnitsIndicator {
|
||||
public double value(AltosState state, int i) { return state.height(); }
|
||||
|
||||
public Height (Container container, int x, int y) {
|
||||
super (container, x, y, AltosConvert.height, "Height");
|
||||
}
|
||||
}
|
||||
|
||||
class Speed extends AltosUIUnitsIndicator {
|
||||
public double value(AltosState state, int i) { return state.speed(); }
|
||||
|
||||
public Speed (Container container, int x, int y) {
|
||||
super (container, x, y, AltosConvert.speed, "Speed");
|
||||
}
|
||||
}
|
||||
|
||||
class Lat extends AltosUIUnitsIndicator {
|
||||
|
||||
public boolean hide (AltosState state, int i) { return state.gps == null || !state.gps.connected; }
|
||||
|
||||
public double value(AltosState state, int i) {
|
||||
if (state.gps == null)
|
||||
return AltosLib.MISSING;
|
||||
if (!state.gps.connected)
|
||||
return AltosLib.MISSING;
|
||||
return state.gps.lat;
|
||||
}
|
||||
|
||||
public Lat (Container container, int x, int y) {
|
||||
super (container, x, y, AltosConvert.latitude, "Latitude");
|
||||
}
|
||||
}
|
||||
|
||||
class Lon extends AltosUIUnitsIndicator {
|
||||
public boolean hide (AltosState state, int i) { return state.gps == null || !state.gps.connected; }
|
||||
|
||||
public double value(AltosState state, int i) {
|
||||
if (state.gps == null)
|
||||
return AltosLib.MISSING;
|
||||
if (!state.gps.connected)
|
||||
return AltosLib.MISSING;
|
||||
return state.gps.lon;
|
||||
}
|
||||
|
||||
public Lon (Container container, int x, int y) {
|
||||
super (container, x, y, AltosConvert.longitude, "Longitude");
|
||||
}
|
||||
}
|
||||
|
||||
class Apogee extends AltosUIUnitsIndicator {
|
||||
public boolean hide(double v) { return v == AltosLib.MISSING; }
|
||||
public double value(AltosState state, int i) { return state.apogee_voltage; }
|
||||
public double good() { return AltosLib.ao_igniter_good; }
|
||||
|
||||
public Apogee (Container container, int y) {
|
||||
super(container, 0, y, 3, AltosConvert.voltage, "Apogee Igniter Voltage", 1, true, 3);
|
||||
}
|
||||
}
|
||||
|
||||
class Main extends AltosUIUnitsIndicator {
|
||||
public boolean hide(double v) { return v == AltosLib.MISSING; }
|
||||
public double value(AltosState state, int i) { return state.main_voltage; }
|
||||
public double good() { return AltosLib.ao_igniter_good; }
|
||||
|
||||
public Main (Container container, int y) {
|
||||
super(container, 0, y, 3, AltosConvert.voltage, "Main Igniter Voltage", 1, true, 3);
|
||||
}
|
||||
}
|
||||
|
||||
class Distance extends AltosUIUnitsIndicator {
|
||||
public double value(AltosState state, int i) {
|
||||
if (state.from_pad != null)
|
||||
return state.from_pad.distance;
|
||||
else
|
||||
return AltosLib.MISSING;
|
||||
}
|
||||
|
||||
public Distance(Container container, int x, int y) {
|
||||
super(container, x, y, AltosConvert.distance, "Ground Distance");
|
||||
}
|
||||
}
|
||||
|
||||
class Range extends AltosUIUnitsIndicator {
|
||||
public double value(AltosState state, int i) {
|
||||
return state.range;
|
||||
}
|
||||
public Range (Container container, int x, int y) {
|
||||
super (container, x, y, AltosConvert.distance, "Range");
|
||||
}
|
||||
}
|
||||
|
||||
class Bearing extends AltosUIIndicator {
|
||||
public void show (AltosState state, AltosListenerState listener_state) {
|
||||
if (state.from_pad != null && state.from_pad.bearing != AltosLib.MISSING) {
|
||||
show( String.format("%3.0f°", state.from_pad.bearing),
|
||||
state.from_pad.bearing_words(
|
||||
AltosGreatCircle.BEARING_LONG));
|
||||
} else {
|
||||
show("Missing", "Missing");
|
||||
}
|
||||
}
|
||||
public Bearing (Container container, int x, int y) {
|
||||
super (container, x, y, 1, "Bearing", 2, false, 1, 2);
|
||||
}
|
||||
}
|
||||
|
||||
class Elevation extends AltosUIIndicator {
|
||||
public void show (AltosState state, AltosListenerState listener_state) {
|
||||
if (state.elevation == AltosLib.MISSING)
|
||||
show("Missing");
|
||||
else
|
||||
show("%3.0f°", state.elevation);
|
||||
}
|
||||
public Elevation (Container container, int x, int y) {
|
||||
super (container, x, y, "Elevation", 1, false, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "Descent";
|
||||
}
|
||||
|
||||
public AltosDescent() {
|
||||
/* Elements in descent display */
|
||||
add(new Speed(this, 0, 0));
|
||||
add(new Height(this, 2, 0));
|
||||
add(new Elevation(this, 0, 1));
|
||||
add(new Range(this, 2, 1));
|
||||
add(new Bearing(this, 0, 2));
|
||||
add(new Distance(this, 0, 3));
|
||||
add(new Lat(this, 0, 4));
|
||||
add(new Lon(this, 2, 4));
|
||||
add(new Apogee(this, 5));
|
||||
add(new Main(this, 6));
|
||||
}
|
||||
}
|
30
altosui/AltosDevice.java
Normal file
30
altosui/AltosDevice.java
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright © 2011 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
import libaltosJNI.*;
|
||||
|
||||
public interface AltosDevice {
|
||||
public abstract String toString();
|
||||
public abstract String toShortString();
|
||||
public abstract int getSerial();
|
||||
public abstract String getPath();
|
||||
public abstract boolean matchProduct(int product);
|
||||
public abstract String getErrorString();
|
||||
public SWIGTYPE_p_altos_file open();
|
||||
}
|
325
altosui/AltosFlightStatus.java
Normal file
325
altosui/AltosFlightStatus.java
Normal file
@@ -0,0 +1,325 @@
|
||||
/*
|
||||
* Copyright © 2010 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.awt.*;
|
||||
import javax.swing.*;
|
||||
import org.altusmetrum.altoslib_14.*;
|
||||
import org.altusmetrum.altosuilib_14.*;
|
||||
|
||||
public class AltosFlightStatus extends JComponent implements AltosFlightDisplay {
|
||||
GridBagLayout layout;
|
||||
|
||||
public abstract class FlightValue {
|
||||
JLabel label;
|
||||
JTextField value;
|
||||
|
||||
void show() {
|
||||
label.setVisible(true);
|
||||
value.setVisible(true);
|
||||
}
|
||||
|
||||
void hide() {
|
||||
label.setVisible(false);
|
||||
value.setVisible(false);
|
||||
}
|
||||
|
||||
abstract void show(AltosState state, AltosListenerState listener_state);
|
||||
|
||||
void reset() {
|
||||
value.setText("");
|
||||
}
|
||||
|
||||
void set_font() {
|
||||
label.setFont(Altos.status_font);
|
||||
value.setFont(Altos.status_font);
|
||||
}
|
||||
|
||||
void setVisible(boolean visible) {
|
||||
label.setVisible(visible);
|
||||
value.setVisible(visible);
|
||||
}
|
||||
|
||||
public FlightValue (GridBagLayout layout, int x, String text) {
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.insets = new Insets(5, 5, 5, 5);
|
||||
c.anchor = GridBagConstraints.CENTER;
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
c.weightx = 1;
|
||||
c.weighty = 1;
|
||||
|
||||
label = new JLabel(text);
|
||||
label.setFont(Altos.status_font);
|
||||
label.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
c.gridx = x; c.gridy = 0;
|
||||
layout.setConstraints(label, c);
|
||||
add(label);
|
||||
|
||||
value = new JTextField("");
|
||||
value.setEditable(false);
|
||||
value.setFont(Altos.status_font);
|
||||
value.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
c.gridx = x; c.gridy = 1;
|
||||
layout.setConstraints(value, c);
|
||||
add(value);
|
||||
}
|
||||
}
|
||||
|
||||
class Call extends FlightValue {
|
||||
|
||||
String last_call = "";
|
||||
|
||||
boolean same_call(String call) {
|
||||
if (last_call == null)
|
||||
return call == null;
|
||||
else
|
||||
return last_call.equals(call);
|
||||
}
|
||||
|
||||
void show(AltosState state, AltosListenerState listener_state) {
|
||||
if (!same_call(state.cal_data().callsign)) {
|
||||
show();
|
||||
value.setText(state.cal_data().callsign);
|
||||
if (state.cal_data().callsign == null)
|
||||
setVisible(false);
|
||||
else
|
||||
setVisible(true);
|
||||
last_call = state.cal_data().callsign;
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
super.reset();
|
||||
last_call = "";
|
||||
}
|
||||
|
||||
public Call (GridBagLayout layout, int x) {
|
||||
super (layout, x, "Callsign");
|
||||
}
|
||||
}
|
||||
|
||||
Call call;
|
||||
|
||||
class Serial extends FlightValue {
|
||||
|
||||
int last_serial = -1;
|
||||
void show(AltosState state, AltosListenerState listener_state) {
|
||||
AltosCalData cal_data = state.cal_data();
|
||||
if (cal_data.serial != last_serial) {
|
||||
show();
|
||||
if (cal_data.serial == AltosLib.MISSING)
|
||||
value.setText("none");
|
||||
else
|
||||
value.setText(String.format("%d", cal_data.serial));
|
||||
last_serial = cal_data.serial;
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
super.reset();
|
||||
last_serial = -1;
|
||||
}
|
||||
|
||||
public Serial (GridBagLayout layout, int x) {
|
||||
super (layout, x, "Serial");
|
||||
}
|
||||
}
|
||||
|
||||
Serial serial;
|
||||
|
||||
class Flight extends FlightValue {
|
||||
|
||||
int last_flight = -1;
|
||||
|
||||
void show(AltosState state, AltosListenerState listener_state) {
|
||||
AltosCalData cal_data = state.cal_data();
|
||||
if (cal_data.flight != last_flight) {
|
||||
show();
|
||||
if (cal_data.flight == AltosLib.MISSING)
|
||||
value.setText("none");
|
||||
else
|
||||
value.setText(String.format("%d", cal_data.flight));
|
||||
last_flight = cal_data.flight;
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
super.reset();
|
||||
last_flight = -1;
|
||||
}
|
||||
|
||||
public Flight (GridBagLayout layout, int x) {
|
||||
super (layout, x, "Flight");
|
||||
}
|
||||
}
|
||||
|
||||
Flight flight;
|
||||
|
||||
class FlightState extends FlightValue {
|
||||
|
||||
int last_state = -1;
|
||||
|
||||
void show(AltosState state, AltosListenerState listener_state) {
|
||||
if (state.state() != last_state) {
|
||||
if (state.state() == AltosLib.ao_flight_stateless)
|
||||
hide();
|
||||
else {
|
||||
show();
|
||||
value.setText(state.state_name());
|
||||
}
|
||||
last_state = state.state();
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
super.reset();
|
||||
last_state = -1;
|
||||
}
|
||||
|
||||
public FlightState (GridBagLayout layout, int x) {
|
||||
super (layout, x, "State");
|
||||
}
|
||||
}
|
||||
|
||||
FlightState flight_state;
|
||||
|
||||
class RSSI extends FlightValue {
|
||||
|
||||
int last_rssi = 10000;
|
||||
|
||||
void show(AltosState state, AltosListenerState listener_state) {
|
||||
if (state.rssi() != last_rssi) {
|
||||
show();
|
||||
value.setText(String.format("%d", state.rssi()));
|
||||
if (state.rssi == AltosLib.MISSING)
|
||||
setVisible(false);
|
||||
else
|
||||
setVisible(true);
|
||||
last_rssi = state.rssi();
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
super.reset();
|
||||
last_rssi = 10000;
|
||||
}
|
||||
|
||||
public RSSI (GridBagLayout layout, int x) {
|
||||
super (layout, x, "RSSI");
|
||||
}
|
||||
}
|
||||
|
||||
RSSI rssi;
|
||||
|
||||
class LastPacket extends FlightValue {
|
||||
|
||||
long last_secs = -1;
|
||||
|
||||
void show(AltosState state, AltosListenerState listener_state) {
|
||||
if (listener_state.running) {
|
||||
long secs = (System.currentTimeMillis() - state.received_time + 500) / 1000;
|
||||
if (secs != last_secs) {
|
||||
value.setText(String.format("%d", secs));
|
||||
last_secs = secs;
|
||||
}
|
||||
} else {
|
||||
value.setText("done");
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
super.reset();
|
||||
last_secs = -1;
|
||||
}
|
||||
|
||||
public LastPacket(GridBagLayout layout, int x) {
|
||||
super (layout, x, "Age");
|
||||
}
|
||||
}
|
||||
|
||||
LastPacket last_packet;
|
||||
|
||||
public void reset () {
|
||||
call.reset();
|
||||
serial.reset();
|
||||
flight.reset();
|
||||
flight_state.reset();
|
||||
rssi.reset();
|
||||
last_packet.reset();
|
||||
}
|
||||
|
||||
public void font_size_changed(int font_size) {
|
||||
call.set_font();
|
||||
serial.set_font();
|
||||
flight.set_font();
|
||||
flight_state.set_font();
|
||||
rssi.set_font();
|
||||
last_packet.set_font();
|
||||
}
|
||||
|
||||
public void units_changed(boolean imperial_units) {
|
||||
}
|
||||
|
||||
public void show (AltosState state, AltosListenerState listener_state) {
|
||||
call.show(state, listener_state);
|
||||
serial.show(state, listener_state);
|
||||
flight.show(state, listener_state);
|
||||
flight_state.show(state, listener_state);
|
||||
rssi.show(state, listener_state);
|
||||
last_packet.show(state, listener_state);
|
||||
if (!listener_state.running)
|
||||
stop();
|
||||
}
|
||||
|
||||
public int height() {
|
||||
Dimension d = layout.preferredLayoutSize(this);
|
||||
return d.height;
|
||||
}
|
||||
|
||||
public String getName() { return "Flight Status"; }
|
||||
|
||||
AltosFlightStatusUpdate status_update;
|
||||
javax.swing.Timer timer;
|
||||
|
||||
public void start(AltosFlightStatusUpdate status_update) {
|
||||
this.status_update = status_update;
|
||||
timer = new javax.swing.Timer(100, status_update);
|
||||
timer.start();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (timer != null) {
|
||||
timer.stop();
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
|
||||
public AltosFlightStatus() {
|
||||
layout = new GridBagLayout();
|
||||
|
||||
setLayout(layout);
|
||||
|
||||
call = new Call(layout, 0);
|
||||
serial = new Serial(layout, 1);
|
||||
flight = new Flight(layout, 2);
|
||||
flight_state = new FlightState(layout, 3);
|
||||
rssi = new RSSI(layout, 4);
|
||||
last_packet = new LastPacket(layout, 5);
|
||||
}
|
||||
}
|
69
altosui/AltosFlightStatusTableModel.java
Normal file
69
altosui/AltosFlightStatusTableModel.java
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright © 2010 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
import javax.swing.table.*;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.text.*;
|
||||
import java.util.prefs.*;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import org.altusmetrum.altoslib_14.*;
|
||||
|
||||
public class AltosFlightStatusTableModel extends AbstractTableModel {
|
||||
private String[] columnNames = {
|
||||
String.format("Height (%s)", AltosConvert.show_distance_units()),
|
||||
"State",
|
||||
"RSSI (dBm)",
|
||||
String.format("Speed (%s)", AltosConvert.show_speed_unit())
|
||||
};
|
||||
private Object[] data = { 0, "idle", 0, 0 };
|
||||
|
||||
public int getColumnCount() { return columnNames.length; }
|
||||
public int getRowCount() { return 2; }
|
||||
public Object getValueAt(int row, int col) {
|
||||
if (row == 0)
|
||||
return columnNames[col];
|
||||
return data[col];
|
||||
}
|
||||
|
||||
public void setValueAt(Object value, int col) {
|
||||
data[col] = value;
|
||||
fireTableCellUpdated(1, col);
|
||||
}
|
||||
|
||||
public void setValueAt(Object value, int row, int col) {
|
||||
setValueAt(value, col);
|
||||
}
|
||||
|
||||
public void set(AltosState state) {
|
||||
setValueAt(String.format("%1.0f", AltosConvert.distance(state.height), 0);
|
||||
setValueAt(state.data.state(), 1);
|
||||
setValueAt(state.data.rssi, 2);
|
||||
double speed = state.baro_speed;
|
||||
if (state.ascent)
|
||||
speed = state.speed;
|
||||
setValueAt(String.format("%1.0f", AltosConvert.speed(speed)), 3);
|
||||
}
|
||||
}
|
||||
*/
|
42
altosui/AltosFlightStatusUpdate.java
Normal file
42
altosui/AltosFlightStatusUpdate.java
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright © 2012 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.awt.event.*;
|
||||
import org.altusmetrum.altoslib_14.*;
|
||||
|
||||
public class AltosFlightStatusUpdate implements ActionListener {
|
||||
|
||||
public AltosState saved_state;
|
||||
public AltosListenerState saved_listener_state;
|
||||
AltosFlightStatus flightStatus;
|
||||
|
||||
public void actionPerformed (ActionEvent e) {
|
||||
if (saved_state != null) {
|
||||
if (saved_listener_state == null)
|
||||
saved_listener_state = new AltosListenerState();
|
||||
flightStatus.show(saved_state, saved_listener_state);
|
||||
}
|
||||
}
|
||||
|
||||
public AltosFlightStatusUpdate (AltosFlightStatus in_flightStatus) {
|
||||
flightStatus = in_flightStatus;
|
||||
}
|
||||
}
|
||||
|
333
altosui/AltosFlightUI.java
Normal file
333
altosui/AltosFlightUI.java
Normal file
@@ -0,0 +1,333 @@
|
||||
/*
|
||||
* Copyright © 2010 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import org.altusmetrum.altoslib_14.*;
|
||||
import org.altusmetrum.altosuilib_14.*;
|
||||
|
||||
public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {
|
||||
AltosVoice voice;
|
||||
AltosFlightReader reader;
|
||||
AltosDisplayThread thread;
|
||||
|
||||
LinkedList<AltosFlightDisplay> displays;
|
||||
|
||||
JTabbedPane pane;
|
||||
|
||||
AltosPad pad;
|
||||
AltosIgnitor igniter;
|
||||
AltosAscent ascent;
|
||||
AltosDescent descent;
|
||||
AltosLanded landed;
|
||||
AltosCompanionInfo companion;
|
||||
AltosUIMap sitemap;
|
||||
boolean has_map;
|
||||
boolean has_companion;
|
||||
boolean has_state;
|
||||
boolean has_igniter;
|
||||
|
||||
private AltosFlightStatus flightStatus;
|
||||
private AltosInfoTable flightInfo;
|
||||
|
||||
boolean exit_on_close = false;
|
||||
|
||||
JComponent cur_tab = null;
|
||||
JComponent which_tab(AltosState state) {
|
||||
if (state.state() < Altos.ao_flight_boost)
|
||||
return pad;
|
||||
if (state.state() <= Altos.ao_flight_coast)
|
||||
return ascent;
|
||||
if (state.state() <= Altos.ao_flight_main)
|
||||
return descent;
|
||||
if (state.state() == AltosLib.ao_flight_stateless)
|
||||
return descent;
|
||||
return landed;
|
||||
}
|
||||
|
||||
void stop_display() {
|
||||
if (thread != null && thread.isAlive()) {
|
||||
thread.interrupt();
|
||||
try {
|
||||
thread.join();
|
||||
} catch (InterruptedException ie) {}
|
||||
}
|
||||
thread = null;
|
||||
}
|
||||
|
||||
void disconnect() {
|
||||
stop_display();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
for (AltosFlightDisplay d : displays)
|
||||
d.reset();
|
||||
}
|
||||
|
||||
public void font_size_changed(int font_size) {
|
||||
for (AltosFlightDisplay d : displays)
|
||||
d.font_size_changed(font_size);
|
||||
}
|
||||
|
||||
public void units_changed(boolean imperial_units) {
|
||||
for (AltosFlightDisplay d : displays)
|
||||
d.units_changed(imperial_units);
|
||||
}
|
||||
|
||||
AltosFlightStatusUpdate status_update;
|
||||
|
||||
public void show(AltosState state, AltosListenerState listener_state) {
|
||||
status_update.saved_state = state;
|
||||
status_update.saved_listener_state = listener_state;
|
||||
|
||||
if (state == null)
|
||||
state = new AltosState(new AltosCalData());
|
||||
|
||||
if (state.state() != Altos.ao_flight_startup) {
|
||||
if (!has_state) {
|
||||
pane.setTitleAt(0, "Launch Pad");
|
||||
pane.add(ascent, 1);
|
||||
pane.add(descent, 2);
|
||||
pane.add(landed, 3);
|
||||
has_state = true;
|
||||
}
|
||||
}
|
||||
|
||||
JComponent tab = which_tab(state);
|
||||
if (tab != cur_tab) {
|
||||
if (cur_tab == pane.getSelectedComponent())
|
||||
pane.setSelectedComponent(tab);
|
||||
cur_tab = tab;
|
||||
}
|
||||
|
||||
if (igniter.should_show(state)) {
|
||||
if (!has_igniter) {
|
||||
pane.add("Ignitor", igniter);
|
||||
has_igniter = true;
|
||||
}
|
||||
} else {
|
||||
if (has_igniter) {
|
||||
pane.remove(igniter);
|
||||
has_igniter = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (state.companion != null) {
|
||||
if (!has_companion) {
|
||||
pane.add("Companion", companion);
|
||||
has_companion= true;
|
||||
}
|
||||
} else {
|
||||
if (has_companion) {
|
||||
pane.remove(companion);
|
||||
has_companion = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (state.gps != null) {
|
||||
if (!has_map) {
|
||||
pane.add("Site Map", sitemap);
|
||||
has_map = true;
|
||||
}
|
||||
} else {
|
||||
if (has_map) {
|
||||
pane.remove(sitemap);
|
||||
has_map = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (AltosFlightDisplay d : displays) {
|
||||
try {
|
||||
d.show(state, listener_state);
|
||||
} catch (Exception e) {
|
||||
System.out.printf("Exception showing %s\n", d.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void set_exit_on_close() {
|
||||
exit_on_close = true;
|
||||
}
|
||||
|
||||
Container bag;
|
||||
AltosUIFreqList frequencies;
|
||||
AltosUIRateList rates;
|
||||
AltosUITelemetryList telemetries;
|
||||
JLabel telemetry;
|
||||
|
||||
ActionListener show_timer;
|
||||
|
||||
public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) {
|
||||
AltosUIPreferences.set_component(this);
|
||||
|
||||
displays = new LinkedList<AltosFlightDisplay>();
|
||||
|
||||
voice = in_voice;
|
||||
reader = in_reader;
|
||||
|
||||
bag = getScrollablePane();
|
||||
bag.setLayout(new GridBagLayout());
|
||||
|
||||
setTitle(String.format("AltOS %s", reader.name));
|
||||
|
||||
/* Stick channel selector at top of table for telemetry monitoring */
|
||||
if (serial >= 0) {
|
||||
set_inset(3);
|
||||
|
||||
// Frequency menu
|
||||
frequencies = new AltosUIFreqList(AltosUIPreferences.frequency(serial));
|
||||
frequencies.set_product("Monitor");
|
||||
frequencies.set_serial(serial);
|
||||
frequencies.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
double frequency = frequencies.frequency();
|
||||
try {
|
||||
reader.set_frequency(frequency);
|
||||
} catch (TimeoutException te) {
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
reader.save_frequency();
|
||||
}
|
||||
});
|
||||
bag.add (frequencies, constraints(0, 1));
|
||||
|
||||
// Telemetry rate list
|
||||
rates = new AltosUIRateList(AltosUIPreferences.telemetry_rate(serial));
|
||||
rates.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int rate = rates.rate();
|
||||
try {
|
||||
reader.set_telemetry_rate(rate);
|
||||
} catch (TimeoutException te) {
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
reader.save_telemetry_rate();
|
||||
}
|
||||
});
|
||||
rates.setEnabled(reader.supports_telemetry_rate(AltosLib.ao_telemetry_rate_2400));
|
||||
bag.add (rates, constraints(1, 1));
|
||||
|
||||
// Telemetry format list
|
||||
if (reader.supports_telemetry(Altos.ao_telemetry_standard)) {
|
||||
telemetries = new AltosUITelemetryList(serial);
|
||||
telemetries.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int telemetry = telemetries.get_selected();
|
||||
reader.set_telemetry(telemetry);
|
||||
reader.save_telemetry();
|
||||
}
|
||||
});
|
||||
bag.add (telemetries, constraints(2, 1));
|
||||
} else {
|
||||
String version;
|
||||
|
||||
if (reader.supports_telemetry(Altos.ao_telemetry_0_9))
|
||||
version = "Telemetry: 0.9";
|
||||
else if (reader.supports_telemetry(Altos.ao_telemetry_0_8))
|
||||
version = "Telemetry: 0.8";
|
||||
else
|
||||
version = "Telemetry: None";
|
||||
|
||||
telemetry = new JLabel(version);
|
||||
bag.add (telemetry, constraints(2, 1));
|
||||
}
|
||||
next_row();
|
||||
}
|
||||
set_inset(0);
|
||||
|
||||
/* Flight status is always visible */
|
||||
flightStatus = new AltosFlightStatus();
|
||||
displays.add(flightStatus);
|
||||
bag.add(flightStatus, constraints(0, 4, GridBagConstraints.HORIZONTAL));
|
||||
next_row();
|
||||
|
||||
/* The rest of the window uses a tabbed pane to
|
||||
* show one of the alternate data views
|
||||
*/
|
||||
pane = new JTabbedPane();
|
||||
|
||||
pad = new AltosPad();
|
||||
displays.add(pad);
|
||||
pane.add("Status", pad);
|
||||
|
||||
igniter = new AltosIgnitor();
|
||||
displays.add(igniter);
|
||||
ascent = new AltosAscent();
|
||||
displays.add(ascent);
|
||||
descent = new AltosDescent();
|
||||
displays.add(descent);
|
||||
landed = new AltosLanded(reader);
|
||||
displays.add(landed);
|
||||
|
||||
flightInfo = new AltosInfoTable();
|
||||
displays.add(flightInfo);
|
||||
pane.add("Table", new JScrollPane(flightInfo));
|
||||
|
||||
companion = new AltosCompanionInfo();
|
||||
displays.add(companion);
|
||||
has_companion = false;
|
||||
has_state = false;
|
||||
|
||||
sitemap = new AltosUIMap();
|
||||
displays.add(sitemap);
|
||||
has_map = false;
|
||||
|
||||
/* Make the tabbed pane use the rest of the window space */
|
||||
bag.add(pane, constraints(0, 4, GridBagConstraints.BOTH));
|
||||
|
||||
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
|
||||
AltosUIPreferences.register_font_listener(this);
|
||||
AltosPreferences.register_units_listener(this);
|
||||
|
||||
status_update = new AltosFlightStatusUpdate(flightStatus);
|
||||
|
||||
flightStatus.start(status_update);
|
||||
|
||||
addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
flightStatus.stop();
|
||||
disconnect();
|
||||
setVisible(false);
|
||||
dispose();
|
||||
AltosUIPreferences.unregister_font_listener(AltosFlightUI.this);
|
||||
AltosPreferences.unregister_units_listener(AltosFlightUI.this);
|
||||
if (exit_on_close)
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
|
||||
pack();
|
||||
setVisible(true);
|
||||
|
||||
thread = new AltosDisplayThread(this, voice, this, reader);
|
||||
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public AltosFlightUI (AltosVoice in_voice, AltosFlightReader in_reader) {
|
||||
this(in_voice, in_reader, -1);
|
||||
}
|
||||
}
|
154
altosui/AltosGraphUI.java
Normal file
154
altosui/AltosGraphUI.java
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright © 2010 Anthony Towns
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import org.altusmetrum.altoslib_14.*;
|
||||
import org.altusmetrum.altosuilib_14.*;
|
||||
|
||||
import org.jfree.chart.ChartPanel;
|
||||
import org.jfree.chart.JFreeChart;
|
||||
import org.jfree.ui.RefineryUtilities;
|
||||
|
||||
public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, AltosUnitsListener, AltosFilterListener
|
||||
{
|
||||
JTabbedPane pane;
|
||||
AltosGraph graph;
|
||||
AltosUIEnable enable;
|
||||
AltosUIMap map;
|
||||
AltosFlightStats stats;
|
||||
AltosFlightStatsTable statsTable;
|
||||
AltosGPS gps;
|
||||
boolean has_gps;
|
||||
|
||||
void fill_map(AltosFlightSeries flight_series) {
|
||||
boolean any_gps = false;
|
||||
AltosGPSTimeValue gtv_last = null;
|
||||
double gps_pad_altitude = flight_series.cal_data().gps_pad_altitude;;
|
||||
|
||||
if (flight_series.gps_series != null) {
|
||||
for (AltosGPSTimeValue gtv : flight_series.gps_series) {
|
||||
AltosGPS gps = gtv.gps;
|
||||
if (gps != null &&
|
||||
gps.locked &&
|
||||
gps.nsat >= 4) {
|
||||
if (map == null)
|
||||
map = new AltosUIMap();
|
||||
double gps_height = gps.alt - gps_pad_altitude;
|
||||
int state = (int) flight_series.value_before(AltosFlightSeries.state_name, gtv.time);
|
||||
map.show(gps, gtv.time, state, gps_height);
|
||||
this.gps = gps;
|
||||
gtv_last = gtv;
|
||||
has_gps = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gtv_last != null) {
|
||||
int state = (int) flight_series.value_after(AltosFlightSeries.state_name, gtv_last.time);
|
||||
double gps_height = gps.alt - gps_pad_altitude;
|
||||
if (state == AltosLib.ao_flight_landed)
|
||||
map.show(gtv_last.gps, gtv_last.time, state,gps_height);
|
||||
}
|
||||
}
|
||||
|
||||
public void font_size_changed(int font_size) {
|
||||
if (map != null)
|
||||
map.font_size_changed(font_size);
|
||||
if (statsTable != null)
|
||||
statsTable.font_size_changed(font_size);
|
||||
}
|
||||
|
||||
public void units_changed(boolean imperial_units) {
|
||||
if (map != null)
|
||||
map.units_changed(imperial_units);
|
||||
if (enable != null)
|
||||
enable.units_changed(imperial_units);
|
||||
}
|
||||
|
||||
AltosUIFlightSeries flight_series;
|
||||
|
||||
public void filter_changed(double speed_filter, double accel_filter) {
|
||||
flight_series.set_filter(speed_filter, accel_filter);
|
||||
graph.filter_changed();
|
||||
stats = new AltosFlightStats(flight_series);
|
||||
statsTable.filter_changed(stats);
|
||||
}
|
||||
|
||||
public double speed_filter() {
|
||||
return flight_series.speed_filter_width;
|
||||
}
|
||||
|
||||
public double accel_filter() {
|
||||
return flight_series.accel_filter_width;
|
||||
}
|
||||
|
||||
AltosGraphUI(AltosRecordSet set, File file) throws InterruptedException, IOException {
|
||||
super(file.getName());
|
||||
AltosCalData cal_data = set.cal_data();
|
||||
|
||||
|
||||
pane = new JTabbedPane();
|
||||
|
||||
flight_series = new AltosUIFlightSeries(cal_data);
|
||||
|
||||
enable = new AltosUIEnable(this);
|
||||
|
||||
set.capture_series(flight_series);
|
||||
|
||||
flight_series.finish();
|
||||
|
||||
stats = new AltosFlightStats(flight_series);
|
||||
|
||||
graph = new AltosGraph(enable, stats, flight_series);
|
||||
|
||||
statsTable = new AltosFlightStatsTable(stats);
|
||||
|
||||
pane.add("Flight Graph", graph.panel);
|
||||
pane.add("Configure Graph", enable);
|
||||
pane.add("Flight Statistics", statsTable);
|
||||
|
||||
has_gps = false;
|
||||
fill_map(flight_series);
|
||||
if (has_gps)
|
||||
pane.add("Map", map);
|
||||
|
||||
setContentPane (pane);
|
||||
|
||||
AltosUIPreferences.register_font_listener(this);
|
||||
AltosPreferences.register_units_listener(this);
|
||||
|
||||
addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
AltosUIPreferences.unregister_font_listener(AltosGraphUI.this);
|
||||
AltosPreferences.unregister_units_listener(AltosGraphUI.this);
|
||||
}
|
||||
});
|
||||
pack();
|
||||
|
||||
setVisible(true);
|
||||
if (gps != null)
|
||||
map.centre(gps);
|
||||
}
|
||||
}
|
308
altosui/AltosIdleMonitorUI.java
Normal file
308
altosui/AltosIdleMonitorUI.java
Normal file
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* Copyright © 2010 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
import java.io.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.Arrays;
|
||||
import org.altusmetrum.altoslib_14.*;
|
||||
import org.altusmetrum.altosuilib_14.*;
|
||||
|
||||
public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDisplay, AltosIdleMonitorListener, DocumentListener {
|
||||
AltosDevice device;
|
||||
JTabbedPane pane;
|
||||
AltosPad pad;
|
||||
AltosInfoTable flightInfo;
|
||||
AltosFlightStatus flightStatus;
|
||||
AltosIgnitor igniter;
|
||||
AltosIdleMonitor thread;
|
||||
AltosUIMap sitemap;
|
||||
int serial;
|
||||
boolean remote;
|
||||
boolean has_igniter;
|
||||
boolean has_map;
|
||||
|
||||
void stop_display() {
|
||||
if (thread != null) {
|
||||
try {
|
||||
thread.abort();
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
}
|
||||
thread = null;
|
||||
}
|
||||
|
||||
void disconnect() {
|
||||
stop_display();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
pad.reset();
|
||||
flightInfo.clear();
|
||||
}
|
||||
|
||||
public void font_size_changed(int font_size) {
|
||||
pad.font_size_changed(font_size);
|
||||
flightInfo.font_size_changed(font_size);
|
||||
}
|
||||
|
||||
public void units_changed(boolean imperial_units) {
|
||||
pad.units_changed(imperial_units);
|
||||
flightInfo.units_changed(imperial_units);
|
||||
}
|
||||
|
||||
AltosFlightStatusUpdate status_update;
|
||||
|
||||
public void show(AltosState state, AltosListenerState listener_state) {
|
||||
status_update.saved_state = state;
|
||||
if (igniter.should_show(state)) {
|
||||
if (!has_igniter) {
|
||||
pane.add("Ignitor", igniter);
|
||||
has_igniter = true;
|
||||
}
|
||||
} else {
|
||||
if (has_igniter) {
|
||||
pane.remove(igniter);
|
||||
has_igniter = false;
|
||||
}
|
||||
}
|
||||
if (state.gps != null && state.gps.connected) {
|
||||
if (!has_map) {
|
||||
pane.add("Site Map", sitemap);
|
||||
has_map = true;
|
||||
}
|
||||
} else {
|
||||
if (has_map) {
|
||||
pane.remove(sitemap);
|
||||
has_map = false;
|
||||
}
|
||||
}
|
||||
|
||||
// try {
|
||||
pad.show(state, listener_state);
|
||||
flightStatus.show(state, listener_state);
|
||||
flightInfo.show(state, listener_state);
|
||||
if (has_igniter)
|
||||
igniter.show(state, listener_state);
|
||||
if (has_map)
|
||||
sitemap.show(state, listener_state);
|
||||
// } catch (Exception e) {
|
||||
// System.out.print("Show exception " + e);
|
||||
// }
|
||||
}
|
||||
|
||||
public void update(final AltosState state, final AltosListenerState listener_state) {
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
show(state, listener_state);
|
||||
}
|
||||
};
|
||||
SwingUtilities.invokeLater(r);
|
||||
}
|
||||
|
||||
public void failed() {
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
close();
|
||||
}
|
||||
};
|
||||
SwingUtilities.invokeLater(r);
|
||||
}
|
||||
|
||||
public void error(final String reason) {
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
disconnect();
|
||||
JOptionPane.showMessageDialog(AltosIdleMonitorUI.this,
|
||||
reason,
|
||||
"Error fetching data",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
};
|
||||
SwingUtilities.invokeLater(r);
|
||||
}
|
||||
|
||||
Container bag;
|
||||
AltosUIFreqList frequencies;
|
||||
JTextField callsign_value;
|
||||
|
||||
/* DocumentListener interface methods */
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
if (callsign_value != null) {
|
||||
String callsign = callsign_value.getText();
|
||||
System.out.printf("callsign set to %s\n", callsign);
|
||||
thread.set_callsign(callsign);
|
||||
AltosUIPreferences.set_callsign(callsign);
|
||||
}
|
||||
}
|
||||
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
changedUpdate(e);
|
||||
}
|
||||
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
changedUpdate(e);
|
||||
}
|
||||
|
||||
void idle_exception(JFrame owner, Exception e) {
|
||||
if (e instanceof FileNotFoundException) {
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
((FileNotFoundException) e).getMessage(),
|
||||
"Cannot open target device",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} else if (e instanceof AltosSerialInUseException) {
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
String.format("Device \"%s\" already in use",
|
||||
device.toShortString()),
|
||||
"Device in use",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} else if (e instanceof IOException) {
|
||||
IOException ee = (IOException) e;
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
device.toShortString(),
|
||||
ee.getLocalizedMessage(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} else {
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
String.format("Connection to \"%s\" failed",
|
||||
device.toShortString()),
|
||||
"Connection Failed",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
private void close() {
|
||||
try {
|
||||
disconnect();
|
||||
} catch (Exception ex) {
|
||||
System.out.printf("Exception %s\n", ex.toString());
|
||||
for (StackTraceElement el : ex.getStackTrace())
|
||||
System.out.printf("%s\n", el.toString());
|
||||
}
|
||||
setVisible(false);
|
||||
dispose();
|
||||
AltosUIPreferences.unregister_font_listener(AltosIdleMonitorUI.this);
|
||||
}
|
||||
|
||||
public AltosIdleMonitorUI(JFrame in_owner)
|
||||
throws FileNotFoundException, TimeoutException, InterruptedException {
|
||||
|
||||
device = AltosDeviceUIDialog.show(in_owner, Altos.product_any);
|
||||
remote = false;
|
||||
if (device.matchProduct(Altos.product_basestation))
|
||||
remote = true;
|
||||
|
||||
serial = device.getSerial();
|
||||
|
||||
AltosSerial link;
|
||||
try {
|
||||
link = new AltosSerial(device);
|
||||
} catch (Exception ex) {
|
||||
idle_exception(in_owner, ex);
|
||||
return;
|
||||
}
|
||||
link.set_frame(this);
|
||||
|
||||
/* We let the user set the freq/callsign, so don't bother with the cancel dialog */
|
||||
link.set_cancel_enable(false);
|
||||
|
||||
bag = getScrollablePane();
|
||||
bag.setLayout(new GridBagLayout());
|
||||
|
||||
setTitle(String.format("AltOS %s", device.toShortString()));
|
||||
|
||||
/* Stick frequency selector at top of table for telemetry monitoring */
|
||||
if (remote && serial >= 0) {
|
||||
set_inset(3);
|
||||
|
||||
// Frequency menu
|
||||
frequencies = new AltosUIFreqList(AltosUIPreferences.frequency(serial));
|
||||
frequencies.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
double frequency = frequencies.frequency();
|
||||
thread.set_frequency(frequency);
|
||||
AltosUIPreferences.set_frequency(device.getSerial(),
|
||||
frequency);
|
||||
}
|
||||
});
|
||||
bag.add (frequencies, constraints(0, 1));
|
||||
bag.add (new JLabel("Callsign:"), constraints(1, 1));
|
||||
/* Add callsign configuration */
|
||||
callsign_value = new JTextField(AltosUIPreferences.callsign());
|
||||
callsign_value.getDocument().addDocumentListener(this);
|
||||
callsign_value.setToolTipText("Callsign sent in packet mode");
|
||||
bag.add(callsign_value, constraints(2, 1, GridBagConstraints.HORIZONTAL));
|
||||
next_row();
|
||||
}
|
||||
|
||||
set_inset(0);
|
||||
|
||||
/* Flight status is always visible */
|
||||
flightStatus = new AltosFlightStatus();
|
||||
bag.add(flightStatus, constraints(0, 4, GridBagConstraints.HORIZONTAL));
|
||||
|
||||
next_row();
|
||||
|
||||
/* The rest of the window uses a tabbed pane to
|
||||
* show one of the alternate data views
|
||||
*/
|
||||
pane = new JTabbedPane();
|
||||
|
||||
pad = new AltosPad();
|
||||
pane.add("Launch Pad", pad);
|
||||
|
||||
flightInfo = new AltosInfoTable();
|
||||
pane.add("Table", new JScrollPane(flightInfo));
|
||||
|
||||
igniter = new AltosIgnitor();
|
||||
|
||||
sitemap = new AltosUIMap();
|
||||
|
||||
/* Make the tabbed pane use the rest of the window space */
|
||||
bag.add(pane, constraints(0, 4, GridBagConstraints.BOTH));
|
||||
|
||||
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
|
||||
AltosUIPreferences.register_font_listener(this);
|
||||
|
||||
addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
close();
|
||||
}
|
||||
});
|
||||
|
||||
pack();
|
||||
setVisible(true);
|
||||
|
||||
thread = new AltosIdleMonitor(this, link, (boolean) remote);
|
||||
|
||||
thread.set_frequency(AltosUIPreferences.frequency(serial));
|
||||
|
||||
status_update = new AltosFlightStatusUpdate(flightStatus);
|
||||
|
||||
new javax.swing.Timer(100, status_update).start();
|
||||
|
||||
thread.start();
|
||||
}
|
||||
}
|
486
altosui/AltosIgniteUI.java
Normal file
486
altosui/AltosIgniteUI.java
Normal file
@@ -0,0 +1,486 @@
|
||||
/*
|
||||
* Copyright © 2010 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import java.io.*;
|
||||
import java.text.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import org.altusmetrum.altoslib_14.*;
|
||||
import org.altusmetrum.altosuilib_14.*;
|
||||
|
||||
public class AltosIgniteUI
|
||||
extends AltosUIDialog
|
||||
implements ActionListener
|
||||
{
|
||||
AltosDevice device;
|
||||
JFrame owner;
|
||||
JLabel label;
|
||||
JToggleButton arm;
|
||||
JButton fire;
|
||||
javax.swing.Timer timer;
|
||||
JButton close;
|
||||
ButtonGroup group;
|
||||
Boolean opened;
|
||||
|
||||
boolean has_standard;
|
||||
int npyro;
|
||||
|
||||
final static int timeout = 1 * 1000;
|
||||
|
||||
int time_remaining;
|
||||
boolean timer_running;
|
||||
|
||||
int poll_remaining;
|
||||
|
||||
LinkedBlockingQueue<String> command_queue;
|
||||
|
||||
class Igniter {
|
||||
JRadioButton button;
|
||||
JLabel status_label;
|
||||
String name;
|
||||
int status;
|
||||
|
||||
void set_status (int status) {
|
||||
this.status = status;
|
||||
status_label.setText(String.format("\"%s\"", AltosIgnite.status_string(status)));
|
||||
}
|
||||
|
||||
Igniter(AltosIgniteUI ui, String label, String name, int y) {
|
||||
Container pane = getScrollablePane();
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
Insets i = new Insets(4,4,4,4);
|
||||
|
||||
this.name = name;
|
||||
this.status = AltosIgnite.Unknown;
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = y;
|
||||
c.gridwidth = 1;
|
||||
c.anchor = GridBagConstraints.WEST;
|
||||
button = new JRadioButton (label);
|
||||
pane.add(button, c);
|
||||
button.addActionListener(ui);
|
||||
button.setActionCommand(name);
|
||||
group.add(button);
|
||||
|
||||
c.gridx = 1;
|
||||
c.gridy = y;
|
||||
c.gridwidth = 1;
|
||||
c.anchor = GridBagConstraints.WEST;
|
||||
status_label = new JLabel("plenty of text");
|
||||
pane.add(status_label, c);
|
||||
|
||||
status = AltosIgnite.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
Igniter igniters[];
|
||||
|
||||
void set_status(String _name, int _status) {
|
||||
|
||||
final String name = _name;
|
||||
final int status = _status;
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
for (int p = 0; p < igniters.length; p++)
|
||||
if (name.equals(igniters[p].name))
|
||||
igniters[p].set_status(status);
|
||||
}
|
||||
};
|
||||
SwingUtilities.invokeLater(r);
|
||||
}
|
||||
|
||||
class IgniteHandler implements Runnable {
|
||||
AltosIgnite ignite;
|
||||
JFrame owner;
|
||||
AltosLink link;
|
||||
|
||||
void send_exception(Exception e) {
|
||||
final Exception f_e = e;
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
ignite_exception(f_e);
|
||||
}
|
||||
};
|
||||
SwingUtilities.invokeLater(r);
|
||||
}
|
||||
|
||||
public void run () {
|
||||
try {
|
||||
ignite = new AltosIgnite(link,
|
||||
device.matchProduct(Altos.product_basestation));
|
||||
|
||||
} catch (Exception e) {
|
||||
send_exception(e);
|
||||
return;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
Runnable r;
|
||||
|
||||
try {
|
||||
String command = command_queue.take();
|
||||
String reply = null;
|
||||
|
||||
if (command.equals("get_status")) {
|
||||
HashMap<String,Integer> status_map = ignite.status();
|
||||
|
||||
for (int p = 0; p < igniters.length; p++) {
|
||||
Integer i = status_map.get(igniters[p].name);
|
||||
if (i != null)
|
||||
set_status(igniters[p].name, i);
|
||||
}
|
||||
reply = "status";
|
||||
} else if (command.equals("get_npyro")) {
|
||||
reply = String.format("npyro %d %d", ignite.npyro(), ignite.has_standard() ? 1 : 0);
|
||||
} else if (command.equals("quit")) {
|
||||
ignite.close();
|
||||
break;
|
||||
} else {
|
||||
ignite.fire(command);
|
||||
reply = "fired";
|
||||
}
|
||||
final String f_reply = reply;
|
||||
r = new Runnable() {
|
||||
public void run() {
|
||||
ignite_reply(f_reply);
|
||||
}
|
||||
};
|
||||
SwingUtilities.invokeLater(r);
|
||||
} catch (Exception e) {
|
||||
send_exception(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IgniteHandler(JFrame in_owner, AltosLink in_link) {
|
||||
owner = in_owner;
|
||||
link = in_link;
|
||||
}
|
||||
}
|
||||
|
||||
void ignite_exception(Exception e) {
|
||||
if (e instanceof FileNotFoundException) {
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
((FileNotFoundException) e).getMessage(),
|
||||
"Cannot open target device",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} else if (e instanceof AltosSerialInUseException) {
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
String.format("Device \"%s\" already in use",
|
||||
device.toShortString()),
|
||||
"Device in use",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} else if (e instanceof IOException) {
|
||||
IOException ee = (IOException) e;
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
device.toShortString(),
|
||||
ee.getLocalizedMessage(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} else {
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
String.format("Connection to \"%s\" failed",
|
||||
device.toShortString()),
|
||||
"Connection Failed",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
close();
|
||||
}
|
||||
|
||||
void ignite_reply(String reply) {
|
||||
if (reply.equals("status")) {
|
||||
set_ignite_status();
|
||||
} else if (reply.equals("fired")) {
|
||||
fired();
|
||||
} else if (reply.startsWith("npyro")) {
|
||||
String items[] = reply.split("\\s+");
|
||||
npyro = Integer.parseInt(items[1]);
|
||||
if (npyro == AltosLib.MISSING)
|
||||
npyro = 0;
|
||||
has_standard = Integer.parseInt(items[2]) != 0;
|
||||
make_ui();
|
||||
}
|
||||
}
|
||||
|
||||
void set_arm_text() {
|
||||
if (arm.isSelected())
|
||||
arm.setText(String.format("%d", time_remaining));
|
||||
else
|
||||
arm.setText("Arm");
|
||||
}
|
||||
|
||||
void start_timer() {
|
||||
time_remaining = 10;
|
||||
set_arm_text();
|
||||
timer_running = true;
|
||||
}
|
||||
|
||||
void stop_timer() {
|
||||
time_remaining = 0;
|
||||
fire.setEnabled(false);
|
||||
timer_running = false;
|
||||
arm.setSelected(false);
|
||||
arm.setEnabled(false);
|
||||
set_arm_text();
|
||||
}
|
||||
|
||||
void cancel () {
|
||||
group.clearSelection();
|
||||
fire.setEnabled(false);
|
||||
stop_timer();
|
||||
}
|
||||
|
||||
void send_command(String command) {
|
||||
try {
|
||||
command_queue.put(command);
|
||||
} catch (Exception ex) {
|
||||
ignite_exception(ex);
|
||||
}
|
||||
}
|
||||
|
||||
boolean getting_status = false;
|
||||
|
||||
void set_ignite_status() {
|
||||
getting_status = false;
|
||||
poll_remaining = 2;
|
||||
if (!isVisible())
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
void poll_ignite_status() {
|
||||
if (poll_remaining > 0) {
|
||||
--poll_remaining;
|
||||
return;
|
||||
}
|
||||
if (!getting_status) {
|
||||
getting_status = true;
|
||||
send_command("get_status");
|
||||
}
|
||||
}
|
||||
|
||||
boolean firing = false;
|
||||
|
||||
void start_fire(String which) {
|
||||
if (!firing) {
|
||||
firing = true;
|
||||
send_command(which);
|
||||
}
|
||||
}
|
||||
|
||||
void fired() {
|
||||
firing = false;
|
||||
cancel();
|
||||
}
|
||||
|
||||
void close() {
|
||||
if (opened) {
|
||||
send_command("quit");
|
||||
}
|
||||
if (timer != null)
|
||||
timer.stop();
|
||||
setVisible(false);
|
||||
dispose();
|
||||
}
|
||||
|
||||
void tick_timer() {
|
||||
if (timer_running) {
|
||||
--time_remaining;
|
||||
if (time_remaining <= 0)
|
||||
cancel();
|
||||
else
|
||||
set_arm_text();
|
||||
}
|
||||
poll_ignite_status();
|
||||
}
|
||||
|
||||
void fire() {
|
||||
if (arm.isEnabled() && arm.isSelected() && time_remaining > 0) {
|
||||
String igniter = "none";
|
||||
|
||||
for (int p = 0; p < igniters.length; p++)
|
||||
if (igniters[p].button.isSelected()) {
|
||||
igniter = igniters[p].name;
|
||||
break;
|
||||
}
|
||||
send_command(igniter);
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String cmd = e.getActionCommand();
|
||||
|
||||
for (int p = 0; p < igniters.length; p++)
|
||||
if (cmd.equals(igniters[p].name)) {
|
||||
stop_timer();
|
||||
arm.setEnabled(true);
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmd.equals("arm")) {
|
||||
if (arm.isSelected()) {
|
||||
fire.setEnabled(true);
|
||||
start_timer();
|
||||
} else
|
||||
cancel();
|
||||
}
|
||||
if (cmd.equals("fire"))
|
||||
fire();
|
||||
if (cmd.equals("tick"))
|
||||
tick_timer();
|
||||
if (cmd.equals("close"))
|
||||
close();
|
||||
}
|
||||
|
||||
/* A window listener to catch closing events and tell the config code */
|
||||
class ConfigListener extends WindowAdapter {
|
||||
AltosIgniteUI ui;
|
||||
|
||||
public ConfigListener(AltosIgniteUI this_ui) {
|
||||
ui = this_ui;
|
||||
}
|
||||
|
||||
public void windowClosing(WindowEvent e) {
|
||||
ui.actionPerformed(new ActionEvent(e.getSource(),
|
||||
ActionEvent.ACTION_PERFORMED,
|
||||
"close"));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean open() {
|
||||
command_queue = new LinkedBlockingQueue<String>();
|
||||
|
||||
opened = false;
|
||||
device = AltosDeviceUIDialog.show(owner, Altos.product_any);
|
||||
if (device != null) {
|
||||
try {
|
||||
AltosSerial serial = new AltosSerial(device);
|
||||
serial.set_frame(owner);
|
||||
IgniteHandler handler = new IgniteHandler(owner, serial);
|
||||
Thread t = new Thread(handler);
|
||||
t.start();
|
||||
opened = true;
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
ignite_exception(ex);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void make_ui() {
|
||||
group = new ButtonGroup();
|
||||
|
||||
Container pane = getScrollablePane();
|
||||
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
Insets i = new Insets(4,4,4,4);
|
||||
|
||||
timer = new javax.swing.Timer(timeout, this);
|
||||
timer.setActionCommand("tick");
|
||||
timer_running = false;
|
||||
timer.restart();
|
||||
|
||||
pane.setLayout(new GridBagLayout());
|
||||
|
||||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.CENTER;
|
||||
c.insets = i;
|
||||
c.weightx = 0;
|
||||
c.weighty = 0;
|
||||
|
||||
int y = 0;
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = y;
|
||||
c.gridwidth = 2;
|
||||
c.anchor = GridBagConstraints.CENTER;
|
||||
label = new JLabel ("Fire Igniter");
|
||||
pane.add(label, c);
|
||||
|
||||
y++;
|
||||
|
||||
int nstandard = 0;
|
||||
if (has_standard)
|
||||
nstandard = 2;
|
||||
|
||||
igniters = new Igniter[nstandard + npyro];
|
||||
|
||||
if (has_standard) {
|
||||
igniters[0] = new Igniter(this, "Apogee", AltosIgnite.Apogee, y++);
|
||||
igniters[1] = new Igniter(this, "Main", AltosIgnite.Main, y++);
|
||||
}
|
||||
|
||||
for (int p = 0; p < npyro; p++) {
|
||||
String name = String.format("%d", p);
|
||||
String label = String.format("%c", 'A' + p);
|
||||
igniters[nstandard+p] = new Igniter(this, label, name, y++);
|
||||
}
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = y;
|
||||
c.gridwidth = 1;
|
||||
c.anchor = GridBagConstraints.CENTER;
|
||||
arm = new JToggleButton ("Arm");
|
||||
pane.add(arm, c);
|
||||
arm.addActionListener(this);
|
||||
arm.setActionCommand("arm");
|
||||
arm.setEnabled(false);
|
||||
|
||||
c.gridx = 1;
|
||||
c.gridy = y;
|
||||
c.gridwidth = 1;
|
||||
c.anchor = GridBagConstraints.CENTER;
|
||||
fire = new JButton ("Fire");
|
||||
fire.setEnabled(false);
|
||||
pane.add(fire, c);
|
||||
fire.addActionListener(this);
|
||||
fire.setActionCommand("fire");
|
||||
|
||||
y++;
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = y;
|
||||
c.gridwidth = 2;
|
||||
c.anchor = GridBagConstraints.CENTER;
|
||||
close = new JButton ("Close");
|
||||
pane.add(close, c);
|
||||
close.addActionListener(this);
|
||||
close.setActionCommand("close");
|
||||
|
||||
pack();
|
||||
setLocationRelativeTo(owner);
|
||||
|
||||
addWindowListener(new ConfigListener(this));
|
||||
}
|
||||
|
||||
public AltosIgniteUI(JFrame in_owner) {
|
||||
|
||||
owner = in_owner;
|
||||
|
||||
if (!open())
|
||||
return;
|
||||
|
||||
send_command("get_npyro");
|
||||
}
|
||||
}
|
92
altosui/AltosIgnitor.java
Normal file
92
altosui/AltosIgnitor.java
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright © 2014 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import org.altusmetrum.altoslib_14.*;
|
||||
import org.altusmetrum.altosuilib_14.*;
|
||||
|
||||
public class AltosIgnitor extends AltosUIFlightTab {
|
||||
|
||||
public class Ignitor extends AltosUIUnitsIndicator {
|
||||
int igniter;
|
||||
|
||||
public double value(AltosState state, int i) {
|
||||
if (state.igniter_voltage == null ||
|
||||
state.igniter_voltage.length < igniter)
|
||||
return AltosLib.MISSING;
|
||||
return state.igniter_voltage[igniter];
|
||||
}
|
||||
|
||||
public double good() { return AltosLib.ao_igniter_good; }
|
||||
|
||||
public Ignitor (AltosUIFlightTab container, int y) {
|
||||
super(container, y, AltosConvert.voltage, String.format ("%s Voltage", AltosLib.igniter_name(y)), 1, true, 1);
|
||||
igniter = y;
|
||||
}
|
||||
}
|
||||
|
||||
Ignitor[] igniters;
|
||||
|
||||
public void show(AltosState state, AltosListenerState listener_state) {
|
||||
if (isShowing())
|
||||
make_igniters(state);
|
||||
super.show(state, listener_state);
|
||||
}
|
||||
|
||||
public boolean should_show(AltosState state) {
|
||||
if (state == null)
|
||||
return false;
|
||||
if (state.igniter_voltage == null)
|
||||
return false;
|
||||
return state.igniter_voltage.length > 0;
|
||||
}
|
||||
|
||||
void make_igniters(AltosState state) {
|
||||
int n = (state == null || state.igniter_voltage == null) ? 0 : state.igniter_voltage.length;
|
||||
int old_n = igniters == null ? 0 : igniters.length;
|
||||
|
||||
if (n != old_n) {
|
||||
|
||||
if (igniters != null) {
|
||||
for (int i = 0; i < igniters.length; i++) {
|
||||
remove(igniters[i]);
|
||||
igniters[i].remove(this);
|
||||
igniters = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (n > 0) {
|
||||
setVisible(true);
|
||||
igniters = new Ignitor[n];
|
||||
for (int i = 0; i < n; i++) {
|
||||
igniters[i] = new Ignitor(this, i);
|
||||
add(igniters[i]);
|
||||
}
|
||||
} else
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "Ignitors";
|
||||
}
|
||||
}
|
193
altosui/AltosLanded.java
Normal file
193
altosui/AltosLanded.java
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright © 2010 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import java.io.*;
|
||||
import org.altusmetrum.altoslib_14.*;
|
||||
import org.altusmetrum.altosuilib_14.*;
|
||||
|
||||
public class AltosLanded extends AltosUIFlightTab implements ActionListener {
|
||||
|
||||
class Bearing extends AltosUIIndicator {
|
||||
public void show (AltosState state, AltosListenerState listener_state) {
|
||||
if (state.from_pad != null && state.from_pad.bearing != AltosLib.MISSING) {
|
||||
show( String.format("%3.0f°", state.from_pad.bearing),
|
||||
state.from_pad.bearing_words(
|
||||
AltosGreatCircle.BEARING_LONG));
|
||||
} else {
|
||||
show("Missing", "Missing");
|
||||
}
|
||||
}
|
||||
public Bearing (Container container, int y) {
|
||||
super (container, y, "Bearing", 2);
|
||||
}
|
||||
}
|
||||
|
||||
class Distance extends AltosUIUnitsIndicator {
|
||||
public double value(AltosState state, int i) {
|
||||
if (state.from_pad != null)
|
||||
return state.from_pad.distance;
|
||||
else
|
||||
return AltosLib.MISSING;
|
||||
}
|
||||
|
||||
public Distance(Container container, int y) {
|
||||
super(container, y, AltosConvert.distance, "Ground Distance", 2);
|
||||
}
|
||||
}
|
||||
|
||||
class Lat extends AltosUIUnitsIndicator {
|
||||
|
||||
public boolean hide (AltosState state, int i) { return state.gps == null || !state.gps.connected; }
|
||||
|
||||
public double value(AltosState state, int i) {
|
||||
if (state.gps == null)
|
||||
return AltosLib.MISSING;
|
||||
if (!state.gps.connected)
|
||||
return AltosLib.MISSING;
|
||||
return state.gps.lat;
|
||||
}
|
||||
|
||||
public Lat (Container container, int y) {
|
||||
super (container, y, AltosConvert.latitude, "Latitude", 2);
|
||||
}
|
||||
}
|
||||
|
||||
class Lon extends AltosUIUnitsIndicator {
|
||||
public boolean hide (AltosState state, int i) { return state.gps == null || !state.gps.connected; }
|
||||
|
||||
public double value(AltosState state, int i) {
|
||||
if (state.gps == null)
|
||||
return AltosLib.MISSING;
|
||||
if (!state.gps.connected)
|
||||
return AltosLib.MISSING;
|
||||
return state.gps.lon;
|
||||
}
|
||||
|
||||
public Lon (Container container, int y) {
|
||||
super (container, y, AltosConvert.longitude, "Longitude", 2);
|
||||
}
|
||||
}
|
||||
|
||||
class MaxHeight extends AltosUIUnitsIndicator {
|
||||
public double value(AltosState state, int i) { return state.max_height(); }
|
||||
|
||||
public MaxHeight (Container container, int y) {
|
||||
super (container, y, AltosConvert.height, "Maximum Height", 2);
|
||||
}
|
||||
}
|
||||
|
||||
class MaxSpeed extends AltosUIUnitsIndicator {
|
||||
public double value(AltosState state, int i) { return state.max_speed(); }
|
||||
|
||||
public MaxSpeed (Container container, int y) {
|
||||
super (container, y, AltosConvert.speed, "Maximum Speed", 2);
|
||||
}
|
||||
}
|
||||
|
||||
class MaxAccel extends AltosUIUnitsIndicator {
|
||||
public double value(AltosState state, int i) { return state.max_acceleration(); }
|
||||
|
||||
public MaxAccel (Container container, int y) {
|
||||
super (container, y, AltosConvert.speed, "Maximum acceleration", 2);
|
||||
}
|
||||
}
|
||||
|
||||
JButton graph;
|
||||
AltosFlightReader reader;
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String cmd = e.getActionCommand();
|
||||
|
||||
if (cmd.equals("graph")) {
|
||||
File file = reader.backing_file();
|
||||
if (file != null) {
|
||||
String filename = file.getName();
|
||||
try {
|
||||
AltosRecordSet record_set = null;
|
||||
FileInputStream in = new FileInputStream(file);
|
||||
if (filename.endsWith("eeprom")) {
|
||||
record_set = new AltosEepromRecordSet(in);
|
||||
} else if (filename.endsWith("telem")) {
|
||||
record_set = new AltosTelemetryFile(in);
|
||||
} else {
|
||||
throw new FileNotFoundException(filename);
|
||||
}
|
||||
try {
|
||||
new AltosGraphUI(record_set, file);
|
||||
} catch (InterruptedException ie) {
|
||||
} catch (IOException ie) {
|
||||
}
|
||||
} catch (FileNotFoundException fe) {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
fe.getMessage(),
|
||||
"Cannot open file",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} catch (IOException ie) {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
ie.getMessage(),
|
||||
"Error reading file file",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "Landed";
|
||||
}
|
||||
|
||||
public void show(AltosState state, AltosListenerState listener_state) {
|
||||
super.show(state, listener_state);
|
||||
if (reader.backing_file() != null)
|
||||
graph.setEnabled(true);
|
||||
}
|
||||
|
||||
public AltosLanded(AltosFlightReader in_reader) {
|
||||
reader = in_reader;
|
||||
|
||||
/* Elements in descent display */
|
||||
add(new Bearing(this, 0));
|
||||
add(new Distance(this, 1));
|
||||
add(new Lat(this, 2));
|
||||
add(new Lon(this, 3));
|
||||
add(new MaxHeight(this, 4));
|
||||
add(new MaxSpeed(this, 5));
|
||||
add(new MaxAccel(this, 6));
|
||||
|
||||
graph = new JButton ("Graph Flight");
|
||||
graph.setActionCommand("graph");
|
||||
graph.addActionListener(this);
|
||||
graph.setEnabled(false);
|
||||
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
|
||||
c.gridx = 1; c.gridy = 7;
|
||||
c.insets = new Insets(10, 10, 10, 10);
|
||||
c.anchor = GridBagConstraints.WEST;
|
||||
c.weightx = 0;
|
||||
c.weighty = 0;
|
||||
c.fill = GridBagConstraints.VERTICAL;
|
||||
add(graph, c);
|
||||
addHierarchyListener(this);
|
||||
}
|
||||
}
|
198
altosui/AltosLaunch.java
Normal file
198
altosui/AltosLaunch.java
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Copyright © 2010 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.awt.*;
|
||||
import org.altusmetrum.altosuilib_14.*;
|
||||
|
||||
public class AltosLaunch {
|
||||
AltosDevice device;
|
||||
AltosSerial serial;
|
||||
boolean serial_started;
|
||||
int launcher_serial;
|
||||
int launcher_channel;
|
||||
int rssi;
|
||||
|
||||
final static int Unknown = -1;
|
||||
final static int Good = 0;
|
||||
final static int Bad = 1;
|
||||
|
||||
int armed;
|
||||
int igniter;
|
||||
|
||||
private void start_serial() throws InterruptedException {
|
||||
serial_started = true;
|
||||
}
|
||||
|
||||
private void stop_serial() throws InterruptedException {
|
||||
if (!serial_started)
|
||||
return;
|
||||
serial_started = false;
|
||||
if (serial == null)
|
||||
return;
|
||||
}
|
||||
|
||||
class string_ref {
|
||||
String value;
|
||||
|
||||
public String get() {
|
||||
return value;
|
||||
}
|
||||
public void set(String i) {
|
||||
value = i;
|
||||
}
|
||||
public string_ref() {
|
||||
value = null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean get_string(String line, String label, string_ref s) {
|
||||
if (line.startsWith(label)) {
|
||||
String quoted = line.substring(label.length()).trim();
|
||||
|
||||
if (quoted.startsWith("\""))
|
||||
quoted = quoted.substring(1);
|
||||
if (quoted.endsWith("\""))
|
||||
quoted = quoted.substring(0,quoted.length()-1);
|
||||
s.set(quoted);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean status() throws InterruptedException, TimeoutException {
|
||||
boolean ok = false;
|
||||
if (serial == null)
|
||||
return false;
|
||||
string_ref status_name = new string_ref();
|
||||
start_serial();
|
||||
serial.printf("l %d %d\n", launcher_serial, launcher_channel);
|
||||
for (;;) {
|
||||
String line = serial.get_reply(20000);
|
||||
if (line == null)
|
||||
throw new TimeoutException();
|
||||
if (get_string(line, "Rssi: ", status_name)) {
|
||||
try {
|
||||
rssi = (int) Altos.fromdec(status_name.get());
|
||||
} catch (NumberFormatException ne) {
|
||||
}
|
||||
break;
|
||||
} else if (get_string(line, "Armed: ", status_name)) {
|
||||
armed = Good;
|
||||
String status = status_name.get();
|
||||
if (status.startsWith("igniter good"))
|
||||
igniter = Good;
|
||||
else if (status.startsWith("igniter bad"))
|
||||
igniter = Bad;
|
||||
else
|
||||
igniter = Unknown;
|
||||
ok = true;
|
||||
} else if (get_string(line, "Disarmed: ", status_name)) {
|
||||
armed = Bad;
|
||||
if (status_name.get().startsWith("igniter good"))
|
||||
igniter = Good;
|
||||
else if (status_name.get().startsWith("igniter bad"))
|
||||
igniter = Bad;
|
||||
else
|
||||
igniter = Unknown;
|
||||
ok = true;
|
||||
} else if (get_string(line, "Error ", status_name)) {
|
||||
armed = Unknown;
|
||||
igniter = Unknown;
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
stop_serial();
|
||||
if (!ok) {
|
||||
armed = Unknown;
|
||||
igniter = Unknown;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
public static String status_string(int status) {
|
||||
switch (status) {
|
||||
case Good:
|
||||
return "good";
|
||||
case Bad:
|
||||
return "open";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
public void arm() {
|
||||
if (serial == null)
|
||||
return;
|
||||
try {
|
||||
start_serial();
|
||||
serial.printf("a %d %d\n", launcher_serial, launcher_channel);
|
||||
serial.flush_output();
|
||||
} catch (InterruptedException ie) {
|
||||
} finally {
|
||||
try {
|
||||
stop_serial();
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void fire() {
|
||||
if (serial == null)
|
||||
return;
|
||||
try {
|
||||
start_serial();
|
||||
serial.printf("i %d %d\n", launcher_serial, launcher_channel);
|
||||
serial.flush_output();
|
||||
} catch (InterruptedException ie) {
|
||||
} finally {
|
||||
try {
|
||||
stop_serial();
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
stop_serial();
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
serial.close();
|
||||
serial = null;
|
||||
}
|
||||
|
||||
public void set_frame(Frame frame) {
|
||||
serial.set_frame(frame);
|
||||
}
|
||||
|
||||
public void set_remote(int in_serial, int in_channel) {
|
||||
launcher_serial = in_serial;
|
||||
launcher_channel = in_channel;
|
||||
}
|
||||
|
||||
public AltosLaunch(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException {
|
||||
|
||||
device = in_device;
|
||||
serial = new AltosSerial(device);
|
||||
}
|
||||
}
|
513
altosui/AltosLaunchUI.java
Normal file
513
altosui/AltosLaunchUI.java
Normal file
@@ -0,0 +1,513 @@
|
||||
/*
|
||||
* Copyright © 2010 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import java.io.*;
|
||||
import java.text.*;
|
||||
import java.util.concurrent.*;
|
||||
import org.altusmetrum.altosuilib_14.*;
|
||||
|
||||
class FireButton extends JButton {
|
||||
protected void processMouseEvent(MouseEvent e) {
|
||||
super.processMouseEvent(e);
|
||||
switch (e.getID()) {
|
||||
case MouseEvent.MOUSE_PRESSED:
|
||||
if (actionListener != null)
|
||||
actionListener.actionPerformed(new ActionEvent(this, e.getID(), "fire_down"));
|
||||
break;
|
||||
case MouseEvent.MOUSE_RELEASED:
|
||||
if (actionListener != null)
|
||||
actionListener.actionPerformed(new ActionEvent(this, e.getID(), "fire_up"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public FireButton(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
|
||||
public class AltosLaunchUI
|
||||
extends AltosUIDialog
|
||||
implements ActionListener
|
||||
{
|
||||
AltosDevice device;
|
||||
JFrame owner;
|
||||
JLabel label;
|
||||
|
||||
int radio_channel;
|
||||
JLabel radio_channel_label;
|
||||
JTextField radio_channel_text;
|
||||
|
||||
int launcher_serial;
|
||||
JLabel launcher_serial_label;
|
||||
JTextField launcher_serial_text;
|
||||
|
||||
int launcher_channel;
|
||||
JLabel launcher_channel_label;
|
||||
JTextField launcher_channel_text;
|
||||
|
||||
JLabel armed_label;
|
||||
JLabel armed_status_label;
|
||||
JLabel igniter;
|
||||
JLabel igniter_status_label;
|
||||
JToggleButton arm;
|
||||
FireButton fire;
|
||||
javax.swing.Timer arm_timer;
|
||||
javax.swing.Timer fire_timer;
|
||||
|
||||
boolean firing;
|
||||
boolean armed;
|
||||
int armed_status;
|
||||
int igniter_status;
|
||||
int rssi;
|
||||
|
||||
final static int arm_timeout = 1 * 1000;
|
||||
final static int fire_timeout = 250;
|
||||
|
||||
int armed_count;
|
||||
|
||||
LinkedBlockingQueue<String> command_queue;
|
||||
|
||||
class LaunchHandler implements Runnable {
|
||||
AltosLaunch launch;
|
||||
JFrame owner;
|
||||
|
||||
void send_exception(Exception e) {
|
||||
final Exception f_e = e;
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
launch_exception(f_e);
|
||||
}
|
||||
};
|
||||
SwingUtilities.invokeLater(r);
|
||||
}
|
||||
|
||||
public void run () {
|
||||
try {
|
||||
launch = new AltosLaunch(device);
|
||||
} catch (Exception e) {
|
||||
send_exception(e);
|
||||
return;
|
||||
}
|
||||
launch.set_frame(owner);
|
||||
launch.set_remote(launcher_serial, launcher_channel);
|
||||
|
||||
for (;;) {
|
||||
Runnable r;
|
||||
|
||||
try {
|
||||
String command = command_queue.take();
|
||||
String reply = null;
|
||||
|
||||
if (command.equals("get_status")) {
|
||||
launch.status();
|
||||
reply = "status";
|
||||
armed_status = launch.armed;
|
||||
igniter_status = launch.igniter;
|
||||
rssi = launch.rssi;
|
||||
} else if (command.equals("set_remote")) {
|
||||
launch.set_remote(launcher_serial, launcher_channel);
|
||||
reply = "remote set";
|
||||
} else if (command.equals("arm")) {
|
||||
launch.arm();
|
||||
reply = "armed";
|
||||
} else if (command.equals("fire")) {
|
||||
launch.fire();
|
||||
reply = "fired";
|
||||
} else if (command.equals("quit")) {
|
||||
launch.close();
|
||||
break;
|
||||
} else {
|
||||
throw new ParseException(String.format("invalid command %s", command), 0);
|
||||
}
|
||||
final String f_reply = reply;
|
||||
r = new Runnable() {
|
||||
public void run() {
|
||||
launch_reply(f_reply);
|
||||
}
|
||||
};
|
||||
SwingUtilities.invokeLater(r);
|
||||
} catch (Exception e) {
|
||||
send_exception(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public LaunchHandler(JFrame in_owner) {
|
||||
owner = in_owner;
|
||||
}
|
||||
}
|
||||
|
||||
void launch_exception(Exception e) {
|
||||
if (e instanceof FileNotFoundException) {
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
((FileNotFoundException) e).getMessage(),
|
||||
"Cannot open target device",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} else if (e instanceof AltosSerialInUseException) {
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
String.format("Device \"%s\" already in use",
|
||||
device.toShortString()),
|
||||
"Device in use",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} else if (e instanceof IOException) {
|
||||
IOException ee = (IOException) e;
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
device.toShortString(),
|
||||
ee.getLocalizedMessage(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} else {
|
||||
JOptionPane.showMessageDialog(owner,
|
||||
String.format("Connection to \"%s\" failed",
|
||||
device.toShortString()),
|
||||
"Connection Failed",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
close();
|
||||
}
|
||||
|
||||
void launch_reply(String reply) {
|
||||
if (reply == null)
|
||||
return;
|
||||
if (reply.equals("remote set"))
|
||||
poll_launch_status();
|
||||
if (reply.equals("status")) {
|
||||
set_launch_status();
|
||||
}
|
||||
}
|
||||
|
||||
void set_arm_text() {
|
||||
if (arm.isSelected())
|
||||
arm.setText(String.format("%d", armed_count));
|
||||
else
|
||||
arm.setText("Arm");
|
||||
}
|
||||
|
||||
void start_arm_timer() {
|
||||
armed_count = 30;
|
||||
set_arm_text();
|
||||
}
|
||||
|
||||
void stop_arm_timer() {
|
||||
armed_count = 0;
|
||||
armed = false;
|
||||
arm.setSelected(false);
|
||||
fire.setEnabled(false);
|
||||
set_arm_text();
|
||||
}
|
||||
|
||||
void cancel () {
|
||||
fire.setEnabled(false);
|
||||
firing = false;
|
||||
stop_arm_timer();
|
||||
}
|
||||
|
||||
void send_command(String command) {
|
||||
try {
|
||||
command_queue.put(command);
|
||||
} catch (Exception ex) {
|
||||
launch_exception(ex);
|
||||
}
|
||||
}
|
||||
|
||||
boolean getting_status = false;
|
||||
|
||||
void set_launch_status() {
|
||||
getting_status = false;
|
||||
armed_status_label.setText(String.format("\"%s\"", AltosLaunch.status_string(armed_status)));
|
||||
igniter_status_label.setText(String.format("\"%s\"", AltosLaunch.status_string(igniter_status)));
|
||||
}
|
||||
|
||||
void poll_launch_status() {
|
||||
if (!getting_status && !firing && !armed) {
|
||||
getting_status = true;
|
||||
send_command("get_status");
|
||||
}
|
||||
}
|
||||
|
||||
void fired() {
|
||||
firing = false;
|
||||
cancel();
|
||||
}
|
||||
|
||||
void close() {
|
||||
send_command("quit");
|
||||
arm_timer.stop();
|
||||
setVisible(false);
|
||||
dispose();
|
||||
}
|
||||
|
||||
void tick_arm_timer() {
|
||||
if (armed_count > 0) {
|
||||
--armed_count;
|
||||
if (armed_count <= 0) {
|
||||
armed_count = 0;
|
||||
cancel();
|
||||
} else {
|
||||
if (!firing) {
|
||||
send_command("arm");
|
||||
set_arm_text();
|
||||
}
|
||||
}
|
||||
}
|
||||
poll_launch_status();
|
||||
}
|
||||
|
||||
void arm() {
|
||||
if (arm.isSelected()) {
|
||||
fire.setEnabled(true);
|
||||
start_arm_timer();
|
||||
if (!firing)
|
||||
send_command("arm");
|
||||
armed = true;
|
||||
} else
|
||||
cancel();
|
||||
}
|
||||
|
||||
void fire_more() {
|
||||
if (firing)
|
||||
send_command("fire");
|
||||
}
|
||||
|
||||
void fire_down() {
|
||||
if (arm.isEnabled() && arm.isSelected() && armed_count > 0) {
|
||||
firing = true;
|
||||
fire_more();
|
||||
fire_timer.restart();
|
||||
}
|
||||
}
|
||||
|
||||
void fire_up() {
|
||||
firing = false;
|
||||
fire_timer.stop();
|
||||
}
|
||||
|
||||
void set_radio() {
|
||||
try {
|
||||
radio_channel = Integer.parseInt(radio_channel_text.getText());
|
||||
} catch (NumberFormatException ne) {
|
||||
radio_channel_text.setText(String.format("%d", radio_channel));
|
||||
}
|
||||
}
|
||||
|
||||
void set_serial() {
|
||||
try {
|
||||
launcher_serial = Integer.parseInt(launcher_serial_text.getText());
|
||||
AltosUIPreferences.set_launcher_serial(launcher_serial);
|
||||
send_command("set_remote");
|
||||
} catch (NumberFormatException ne) {
|
||||
launcher_serial_text.setText(String.format("%d", launcher_serial));
|
||||
}
|
||||
}
|
||||
|
||||
void set_channel() {
|
||||
try {
|
||||
launcher_channel = Integer.parseInt(launcher_channel_text.getText());
|
||||
AltosUIPreferences.set_launcher_serial(launcher_channel);
|
||||
send_command("set_remote");
|
||||
} catch (NumberFormatException ne) {
|
||||
launcher_channel_text.setText(String.format("%d", launcher_channel));
|
||||
}
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String cmd = e.getActionCommand();
|
||||
if (cmd.equals("armed") || cmd.equals("igniter")) {
|
||||
stop_arm_timer();
|
||||
}
|
||||
|
||||
if (cmd.equals("arm"))
|
||||
arm();
|
||||
if (cmd.equals("tick_arm"))
|
||||
tick_arm_timer();
|
||||
if (cmd.equals("close"))
|
||||
close();
|
||||
if (cmd.equals("fire_down"))
|
||||
fire_down();
|
||||
if (cmd.equals("fire_up"))
|
||||
fire_up();
|
||||
if (cmd.equals("tick_fire"))
|
||||
fire_more();
|
||||
if (cmd.equals("new_serial"))
|
||||
set_serial();
|
||||
if (cmd.equals("new_channel"))
|
||||
set_channel();
|
||||
}
|
||||
|
||||
/* A window listener to catch closing events and tell the config code */
|
||||
class ConfigListener extends WindowAdapter {
|
||||
AltosLaunchUI ui;
|
||||
|
||||
public ConfigListener(AltosLaunchUI this_ui) {
|
||||
ui = this_ui;
|
||||
}
|
||||
|
||||
public void windowClosing(WindowEvent e) {
|
||||
ui.actionPerformed(new ActionEvent(e.getSource(),
|
||||
ActionEvent.ACTION_PERFORMED,
|
||||
"close"));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean open() {
|
||||
command_queue = new LinkedBlockingQueue<String>();
|
||||
|
||||
device = AltosDeviceUIDialog.show(owner, Altos.product_any);
|
||||
if (device != null) {
|
||||
LaunchHandler handler = new LaunchHandler(owner);
|
||||
Thread t = new Thread(handler);
|
||||
t.start();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public AltosLaunchUI(JFrame in_owner) {
|
||||
|
||||
launcher_channel = AltosUIPreferences.launcher_channel();
|
||||
launcher_serial = AltosUIPreferences.launcher_serial();
|
||||
owner = in_owner;
|
||||
armed_status = AltosLaunch.Unknown;
|
||||
igniter_status = AltosLaunch.Unknown;
|
||||
|
||||
if (!open())
|
||||
return;
|
||||
|
||||
Container pane = getScrollablePane();
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
Insets i = new Insets(4,4,4,4);
|
||||
|
||||
arm_timer = new javax.swing.Timer(arm_timeout, this);
|
||||
arm_timer.setActionCommand("tick_arm");
|
||||
arm_timer.restart();
|
||||
|
||||
fire_timer = new javax.swing.Timer(fire_timeout, this);
|
||||
fire_timer.setActionCommand("tick_fire");
|
||||
|
||||
owner = in_owner;
|
||||
|
||||
pane.setLayout(new GridBagLayout());
|
||||
|
||||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.CENTER;
|
||||
c.insets = i;
|
||||
c.weightx = 1;
|
||||
c.weighty = 1;
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = 0;
|
||||
c.gridwidth = 2;
|
||||
c.anchor = GridBagConstraints.CENTER;
|
||||
label = new JLabel ("Launch Controller");
|
||||
pane.add(label, c);
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = 1;
|
||||
c.gridwidth = 1;
|
||||
c.anchor = GridBagConstraints.WEST;
|
||||
launcher_serial_label = new JLabel("Launcher Serial");
|
||||
pane.add(launcher_serial_label, c);
|
||||
|
||||
c.gridx = 1;
|
||||
c.gridy = 1;
|
||||
c.gridwidth = 1;
|
||||
c.anchor = GridBagConstraints.WEST;
|
||||
launcher_serial_text = new JTextField(7);
|
||||
launcher_serial_text.setText(String.format("%d", launcher_serial));
|
||||
launcher_serial_text.setActionCommand("new_serial");
|
||||
launcher_serial_text.addActionListener(this);
|
||||
pane.add(launcher_serial_text, c);
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = 2;
|
||||
c.gridwidth = 1;
|
||||
c.anchor = GridBagConstraints.WEST;
|
||||
launcher_channel_label = new JLabel("Launcher Channel");
|
||||
pane.add(launcher_channel_label, c);
|
||||
|
||||
c.gridx = 1;
|
||||
c.gridy = 2;
|
||||
c.gridwidth = 1;
|
||||
c.anchor = GridBagConstraints.WEST;
|
||||
launcher_channel_text = new JTextField(7);
|
||||
launcher_channel_text.setText(String.format("%d", launcher_channel));
|
||||
launcher_channel_text.setActionCommand("new_channel");
|
||||
launcher_channel_text.addActionListener(this);
|
||||
pane.add(launcher_channel_text, c);
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = 3;
|
||||
c.gridwidth = 1;
|
||||
c.anchor = GridBagConstraints.WEST;
|
||||
armed_label = new JLabel ("Armed");
|
||||
pane.add(armed_label, c);
|
||||
|
||||
c.gridx = 1;
|
||||
c.gridy = 3;
|
||||
c.gridwidth = 1;
|
||||
c.anchor = GridBagConstraints.WEST;
|
||||
armed_status_label = new JLabel();
|
||||
pane.add(armed_status_label, c);
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = 4;
|
||||
c.gridwidth = 1;
|
||||
c.anchor = GridBagConstraints.WEST;
|
||||
igniter = new JLabel ("Igniter");
|
||||
pane.add(igniter, c);
|
||||
|
||||
c.gridx = 1;
|
||||
c.gridy = 4;
|
||||
c.gridwidth = 1;
|
||||
c.anchor = GridBagConstraints.WEST;
|
||||
igniter_status_label = new JLabel();
|
||||
pane.add(igniter_status_label, c);
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = 5;
|
||||
c.gridwidth = 1;
|
||||
c.anchor = GridBagConstraints.CENTER;
|
||||
arm = new JToggleButton ("Arm");
|
||||
pane.add(arm, c);
|
||||
arm.addActionListener(this);
|
||||
arm.setActionCommand("arm");
|
||||
arm.setEnabled(true);
|
||||
|
||||
c.gridx = 1;
|
||||
c.gridy = 5;
|
||||
c.gridwidth = 1;
|
||||
c.anchor = GridBagConstraints.CENTER;
|
||||
fire = new FireButton ("Fire");
|
||||
fire.setEnabled(false);
|
||||
pane.add(fire, c);
|
||||
fire.addActionListener(this);
|
||||
fire.setActionCommand("fire");
|
||||
|
||||
pack();
|
||||
setLocationRelativeTo(owner);
|
||||
|
||||
addWindowListener(new ConfigListener(this));
|
||||
|
||||
setVisible(true);
|
||||
}
|
||||
}
|
257
altosui/AltosPad.java
Normal file
257
altosui/AltosPad.java
Normal file
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright © 2010 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.util.*;
|
||||
import org.altusmetrum.altoslib_14.*;
|
||||
import org.altusmetrum.altosuilib_14.*;
|
||||
|
||||
public class AltosPad extends AltosUIFlightTab {
|
||||
|
||||
class Battery extends AltosUIVoltageIndicator {
|
||||
public double voltage(AltosState state) { return state.battery_voltage; }
|
||||
public double good() { return AltosLib.ao_battery_good; }
|
||||
public Battery (AltosUIFlightTab container, int y) { super(container, y, "Battery Voltage", 2); }
|
||||
}
|
||||
|
||||
class Apogee extends AltosUIVoltageIndicator {
|
||||
public boolean hide(double v) { return v == AltosLib.MISSING; }
|
||||
public double voltage(AltosState state) { return state.apogee_voltage; }
|
||||
public double good() { return AltosLib.ao_igniter_good; }
|
||||
public Apogee (AltosUIFlightTab container, int y) { super(container, y, "Apogee Igniter Voltage", 2); }
|
||||
}
|
||||
|
||||
class Main extends AltosUIVoltageIndicator {
|
||||
public boolean hide(double v) { return v == AltosLib.MISSING; }
|
||||
public double voltage(AltosState state) { return state.main_voltage; }
|
||||
public double good() { return AltosLib.ao_igniter_good; }
|
||||
public Main (AltosUIFlightTab container, int y) { super(container, y, "Main Igniter Voltage", 2); }
|
||||
}
|
||||
|
||||
class LoggingReady extends AltosUIIndicator {
|
||||
public void show (AltosState state, AltosListenerState listener_state) {
|
||||
AltosCalData cal_data = state.cal_data();
|
||||
if (state == null || cal_data.flight == AltosLib.MISSING) {
|
||||
hide();
|
||||
} else {
|
||||
if (cal_data.flight != 0) {
|
||||
if (state.state() <= Altos.ao_flight_pad)
|
||||
show("Ready to record");
|
||||
else if (state.state() < Altos.ao_flight_landed ||
|
||||
state.state() == AltosLib.ao_flight_stateless)
|
||||
show("Recording data");
|
||||
else
|
||||
show("Recorded data");
|
||||
} else
|
||||
show("Storage full");
|
||||
set_lights(cal_data.flight != 0);
|
||||
}
|
||||
}
|
||||
public LoggingReady (AltosUIFlightTab container, int y) {
|
||||
super(container, y, "On-board Data Logging", 1, true, 2);
|
||||
}
|
||||
}
|
||||
|
||||
class GPSLocked extends AltosUIIndicator {
|
||||
public void show (AltosState state, AltosListenerState listener_state) {
|
||||
if (state == null || state.gps == null)
|
||||
hide();
|
||||
else {
|
||||
int sol = state.gps.nsat;
|
||||
int sat = state.gps.cc_gps_sat == null ? 0 : state.gps.cc_gps_sat.length;
|
||||
show("%d in solution", sol, "%d in view", sat);
|
||||
set_lights(state.gps.locked && sol >= 4);
|
||||
}
|
||||
}
|
||||
public GPSLocked (AltosUIFlightTab container, int y) {
|
||||
super (container, y, "GPS Locked", 2, true, 1);
|
||||
}
|
||||
}
|
||||
|
||||
class GPSReady extends AltosUIIndicator {
|
||||
public void show (AltosState state, AltosListenerState listener_state) {
|
||||
if (state == null || state.gps == null)
|
||||
hide();
|
||||
else {
|
||||
if (state.gps_ready)
|
||||
show("Ready");
|
||||
else
|
||||
show("Waiting %d", state.gps_waiting);
|
||||
set_lights(state.gps_ready);
|
||||
}
|
||||
}
|
||||
public GPSReady (AltosUIFlightTab container, int y) {
|
||||
super (container, y, "GPS Ready", 1, true, 2);
|
||||
}
|
||||
}
|
||||
|
||||
class ReceiverBattery extends AltosUIVoltageIndicator {
|
||||
|
||||
double last_voltage = AltosLib.MISSING;
|
||||
|
||||
public double voltage(AltosState state) {
|
||||
return last_voltage;
|
||||
}
|
||||
|
||||
public double good() { return AltosLib.ao_battery_good; }
|
||||
|
||||
public boolean hide(AltosState state, AltosListenerState listener_state, int i) {
|
||||
return value(state, listener_state, i) == AltosLib.MISSING;
|
||||
}
|
||||
|
||||
public double value(AltosState state, AltosListenerState listener_state, int i) {
|
||||
if (listener_state == null)
|
||||
last_voltage = AltosLib.MISSING;
|
||||
else
|
||||
last_voltage = listener_state.battery;
|
||||
return last_voltage;
|
||||
}
|
||||
|
||||
public ReceiverBattery (AltosUIFlightTab container, int y) {
|
||||
super(container, y, "Receiver Battery", 2);
|
||||
}
|
||||
}
|
||||
|
||||
boolean report_pad(AltosState state) {
|
||||
if (state.state() == AltosLib.ao_flight_stateless ||
|
||||
state.state() < AltosLib.ao_flight_pad)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
class PadLat extends AltosUIIndicator {
|
||||
|
||||
double last_lat = AltosLib.MISSING - 1;
|
||||
|
||||
public void show (AltosState state, AltosListenerState listener_state) {
|
||||
double lat = AltosLib.MISSING;
|
||||
String label = null;
|
||||
|
||||
if (state != null) {
|
||||
if (report_pad(state)) {
|
||||
lat = state.pad_lat;
|
||||
label = "Pad Latitude";
|
||||
} else if (state.gps != null) {
|
||||
lat = state.gps.lat;
|
||||
label = "Latitude";
|
||||
}
|
||||
}
|
||||
if (lat != last_lat) {
|
||||
if (lat != AltosLib.MISSING) {
|
||||
show(AltosConvert.latitude.show(10, lat));
|
||||
set_label(label);
|
||||
} else
|
||||
hide();
|
||||
last_lat = lat;
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
super.reset();
|
||||
last_lat = AltosLib.MISSING - 1;
|
||||
}
|
||||
|
||||
public PadLat (AltosUIFlightTab container, int y) {
|
||||
super (container, y, "Pad Latitude", 1, false, 2);
|
||||
}
|
||||
}
|
||||
|
||||
class PadLon extends AltosUIIndicator {
|
||||
|
||||
double last_lon = AltosLib.MISSING - 1;
|
||||
|
||||
public void show (AltosState state, AltosListenerState listener_state) {
|
||||
double lon = AltosLib.MISSING;
|
||||
String label = null;
|
||||
|
||||
if (state != null) {
|
||||
if (report_pad(state)) {
|
||||
lon = state.pad_lon;
|
||||
label = "Pad Longitude";
|
||||
} else if (state.gps != null) {
|
||||
lon = state.gps.lon;
|
||||
label = "Longitude";
|
||||
}
|
||||
}
|
||||
if (lon != last_lon) {
|
||||
if (lon != AltosLib.MISSING) {
|
||||
show(AltosConvert.longitude.show(10, lon));
|
||||
set_label(label);
|
||||
} else
|
||||
hide();
|
||||
last_lon = lon;
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
super.reset();
|
||||
last_lon = AltosLib.MISSING - 1;
|
||||
}
|
||||
|
||||
public PadLon (AltosUIFlightTab container, int y) {
|
||||
super (container, y, "Pad Longitude", 1, false, 2);
|
||||
}
|
||||
}
|
||||
|
||||
class PadAlt extends AltosUIUnitsIndicator {
|
||||
|
||||
public double value(AltosState state, int i) {
|
||||
if (report_pad(state)) {
|
||||
double alt = state.gps_ground_altitude();
|
||||
if (alt == AltosLib.MISSING)
|
||||
alt = state.ground_altitude();
|
||||
return alt;
|
||||
}
|
||||
else if (state.gps != null && state.gps.alt != AltosLib.MISSING)
|
||||
return state.gps.alt;
|
||||
else
|
||||
return state.altitude();
|
||||
}
|
||||
|
||||
public void show (AltosState state, AltosListenerState listener_state) {
|
||||
String label = "Altitude";
|
||||
|
||||
if (state != null && report_pad(state))
|
||||
label = "Pad Altitude";
|
||||
set_label(label);
|
||||
super.show(state, listener_state);
|
||||
}
|
||||
|
||||
public PadAlt (AltosUIFlightTab container, int y) {
|
||||
super (container, y, AltosConvert.height, "Pad Altitude", 1, false, 2);
|
||||
}
|
||||
}
|
||||
public String getName() { return "Pad"; }
|
||||
|
||||
public AltosPad() {
|
||||
int y = 0;
|
||||
add(new Battery(this, y++));
|
||||
add(new ReceiverBattery(this, y++));
|
||||
add(new Apogee(this, y++));
|
||||
add(new Main(this, y++));
|
||||
add(new LoggingReady(this, y++));
|
||||
add(new GPSLocked(this, y++));
|
||||
add(new GPSReady(this, y++));
|
||||
add(new PadLat(this, y++));
|
||||
add(new PadLon(this, y++));
|
||||
add(new PadAlt(this, y++));
|
||||
}
|
||||
}
|
906
altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub
Executable file
906
altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub
Executable file
@@ -0,0 +1,906 @@
|
||||
#!/bin/bash
|
||||
##################################################################################
|
||||
# #
|
||||
# universalJavaApplicationStub #
|
||||
# #
|
||||
# A BASH based JavaApplicationStub for Java Apps on Mac OS X #
|
||||
# that works with both Apple's and Oracle's plist format. #
|
||||
# #
|
||||
# Inspired by Ian Roberts stackoverflow answer #
|
||||
# at http://stackoverflow.com/a/17546508/1128689 #
|
||||
# #
|
||||
# @author Tobias Fischer #
|
||||
# @url https://github.com/tofi86/universalJavaApplicationStub #
|
||||
# @date 2021-02-21 #
|
||||
# @version 3.2.0 #
|
||||
# #
|
||||
##################################################################################
|
||||
# #
|
||||
# The MIT License (MIT) #
|
||||
# #
|
||||
# Copyright (c) 2014-2021 Tobias Fischer #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy #
|
||||
# of this software and associated documentation files (the "Software"), to deal #
|
||||
# in the Software without restriction, including without limitation the rights #
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell #
|
||||
# copies of the Software, and to permit persons to whom the Software is #
|
||||
# furnished to do so, subject to the following conditions: #
|
||||
# #
|
||||
# The above copyright notice and this permission notice shall be included in all #
|
||||
# copies or substantial portions of the Software. #
|
||||
# #
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, #
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE #
|
||||
# SOFTWARE. #
|
||||
# #
|
||||
##################################################################################
|
||||
|
||||
#
|
||||
# Fix fonts. I don't know why the getting the
|
||||
# basename of the app set to . matters, but it does
|
||||
#
|
||||
case "$0" in
|
||||
/*)
|
||||
cd `dirname "$0"`
|
||||
./`basename "$0"` "$@"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
export FREETYPE_PROPERTIES=truetype:interpreter-version=35
|
||||
|
||||
# function 'stub_logger()'
|
||||
#
|
||||
# A logger which logs to the macOS Console.app using the 'syslog' command
|
||||
#
|
||||
# @param1 the log message
|
||||
# @return void
|
||||
################################################################################
|
||||
function stub_logger() {
|
||||
syslog -s -k \
|
||||
Facility com.apple.console \
|
||||
Level Notice \
|
||||
Sender "$(basename "$0")" \
|
||||
Message "[$$][${CFBundleName:-$(basename "$0")}] $1"
|
||||
}
|
||||
|
||||
|
||||
|
||||
# set the directory abspath of the current
|
||||
# shell script with symlinks being resolved
|
||||
############################################
|
||||
|
||||
PRG=$0
|
||||
while [ -h "$PRG" ]; do
|
||||
ls=$(ls -ld "$PRG")
|
||||
link=$(expr "$ls" : '^.*-> \(.*\)$' 2>/dev/null)
|
||||
if expr "$link" : '^/' 2> /dev/null >/dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG="$(dirname "$PRG")/$link"
|
||||
fi
|
||||
done
|
||||
PROGDIR=$(dirname "$PRG")
|
||||
stub_logger "[StubDir] $PROGDIR"
|
||||
|
||||
|
||||
|
||||
# set files and folders
|
||||
############################################
|
||||
|
||||
# the absolute path of the app package
|
||||
cd "$PROGDIR"/../../ || exit 11
|
||||
AppPackageFolder=$(pwd)
|
||||
|
||||
# the base path of the app package
|
||||
cd .. || exit 12
|
||||
AppPackageRoot=$(pwd)
|
||||
|
||||
# set Apple's Java folder
|
||||
AppleJavaFolder="${AppPackageFolder}"/Contents/Resources/Java
|
||||
|
||||
# set Apple's Resources folder
|
||||
AppleResourcesFolder="${AppPackageFolder}"/Contents/Resources
|
||||
|
||||
# set Oracle's Java folder
|
||||
OracleJavaFolder="${AppPackageFolder}"/Contents/Java
|
||||
|
||||
# set Oracle's Resources folder
|
||||
OracleResourcesFolder="${AppPackageFolder}"/Contents/Resources
|
||||
|
||||
# set path to Info.plist in bundle
|
||||
InfoPlistFile="${AppPackageFolder}"/Contents/Info.plist
|
||||
|
||||
# set the default JVM Version to a null string
|
||||
JVMVersion=""
|
||||
JVMMaxVersion=""
|
||||
|
||||
|
||||
|
||||
# function 'plist_get()'
|
||||
#
|
||||
# read a specific Plist key with 'PlistBuddy' utility
|
||||
#
|
||||
# @param1 the Plist key with leading colon ':'
|
||||
# @return the value as String or Array
|
||||
################################################################################
|
||||
plist_get(){
|
||||
/usr/libexec/PlistBuddy -c "print $1" "${InfoPlistFile}" 2> /dev/null
|
||||
}
|
||||
|
||||
# function 'plist_get_java()'
|
||||
#
|
||||
# read a specific Plist key with 'PlistBuddy' utility
|
||||
# in the 'Java' or 'JavaX' dictionary (<dict>)
|
||||
#
|
||||
# @param1 the Plist :Java(X):Key with leading colon ':'
|
||||
# @return the value as String or Array
|
||||
################################################################################
|
||||
plist_get_java(){
|
||||
plist_get ${JavaKey:-":Java"}$1
|
||||
}
|
||||
|
||||
|
||||
|
||||
# read Info.plist and extract JVM options
|
||||
############################################
|
||||
|
||||
# read the program name from CFBundleName
|
||||
CFBundleName=$(plist_get ':CFBundleName')
|
||||
|
||||
# read the icon file name
|
||||
CFBundleIconFile=$(plist_get ':CFBundleIconFile')
|
||||
|
||||
|
||||
# check Info.plist for Apple style Java keys -> if key :Java is present, parse in apple mode
|
||||
/usr/libexec/PlistBuddy -c "print :Java" "${InfoPlistFile}" > /dev/null 2>&1
|
||||
exitcode=$?
|
||||
JavaKey=":Java"
|
||||
|
||||
# if no :Java key is present, check Info.plist for universalJavaApplication style JavaX keys -> if key :JavaX is present, parse in apple mode
|
||||
if [ $exitcode -ne 0 ]; then
|
||||
/usr/libexec/PlistBuddy -c "print :JavaX" "${InfoPlistFile}" > /dev/null 2>&1
|
||||
exitcode=$?
|
||||
JavaKey=":JavaX"
|
||||
fi
|
||||
|
||||
|
||||
# read 'Info.plist' file in Apple style if exit code returns 0 (true, ':Java' key is present)
|
||||
if [ $exitcode -eq 0 ]; then
|
||||
stub_logger "[PlistStyle] Apple"
|
||||
|
||||
# set Java and Resources folder
|
||||
JavaFolder="${AppleJavaFolder}"
|
||||
ResourcesFolder="${AppleResourcesFolder}"
|
||||
|
||||
# set expandable variables
|
||||
APP_ROOT="${AppPackageFolder}"
|
||||
APP_PACKAGE="${AppPackageFolder}"
|
||||
JAVAROOT="${AppleJavaFolder}"
|
||||
USER_HOME="$HOME"
|
||||
|
||||
|
||||
# read the Java WorkingDirectory
|
||||
JVMWorkDir=$(plist_get_java ':WorkingDirectory' | xargs)
|
||||
# set Working Directory based upon PList value
|
||||
if [[ ! -z ${JVMWorkDir} ]]; then
|
||||
WorkingDirectory="${JVMWorkDir}"
|
||||
else
|
||||
# AppPackageRoot is the standard WorkingDirectory when the script is started
|
||||
WorkingDirectory="${AppPackageRoot}"
|
||||
fi
|
||||
# expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME
|
||||
WorkingDirectory=$(eval echo "${WorkingDirectory}")
|
||||
|
||||
|
||||
# read the MainClass name
|
||||
JVMMainClass="$(plist_get_java ':MainClass')"
|
||||
|
||||
# read the SplashFile name
|
||||
JVMSplashFile=$(plist_get_java ':SplashFile')
|
||||
|
||||
# read the JVM Properties as an array and retain spaces
|
||||
IFS=$'\t\n'
|
||||
JVMOptions=($(xargs -n1 <<<$(plist_get_java ':Properties' | grep " =" | sed 's/^ */-D/g' | sed -E 's/ = (.*)$/="\1"/g')))
|
||||
unset IFS
|
||||
# post processing of the array follows further below...
|
||||
|
||||
# read the ClassPath in either Array or String style
|
||||
JVMClassPath_RAW=$(plist_get_java ':ClassPath' | xargs)
|
||||
if [[ $JVMClassPath_RAW == *Array* ]] ; then
|
||||
JVMClassPath=.$(plist_get_java ':ClassPath' | grep " " | sed 's/^ */:/g' | tr -d '\n' | xargs)
|
||||
else
|
||||
JVMClassPath=${JVMClassPath_RAW}
|
||||
fi
|
||||
# expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME
|
||||
JVMClassPath=$(eval echo "${JVMClassPath}")
|
||||
|
||||
# read the JVM Options in either Array or String style
|
||||
JVMDefaultOptions_RAW=$(plist_get_java ':VMOptions' | xargs)
|
||||
if [[ $JVMDefaultOptions_RAW == *Array* ]] ; then
|
||||
JVMDefaultOptions=$(plist_get_java ':VMOptions' | grep " " | sed 's/^ */ /g' | tr -d '\n' | xargs)
|
||||
else
|
||||
JVMDefaultOptions=${JVMDefaultOptions_RAW}
|
||||
fi
|
||||
# expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME (#84)
|
||||
JVMDefaultOptions=$(eval echo "${JVMDefaultOptions}")
|
||||
|
||||
# read StartOnMainThread and add as -XstartOnFirstThread
|
||||
JVMStartOnMainThread=$(plist_get_java ':StartOnMainThread')
|
||||
if [ "${JVMStartOnMainThread}" == "true" ]; then
|
||||
JVMDefaultOptions+=" -XstartOnFirstThread"
|
||||
fi
|
||||
|
||||
# read the JVM Arguments in either Array or String style (#76) and retain spaces
|
||||
IFS=$'\t\n'
|
||||
MainArgs_RAW=$(plist_get_java ':Arguments' | xargs)
|
||||
if [[ $MainArgs_RAW == *Array* ]] ; then
|
||||
MainArgs=($(xargs -n1 <<<$(plist_get_java ':Arguments' | tr -d '\n' | sed -E 's/Array \{ *(.*) *\}/\1/g' | sed 's/ */ /g')))
|
||||
else
|
||||
MainArgs=($(xargs -n1 <<<$(plist_get_java ':Arguments')))
|
||||
fi
|
||||
unset IFS
|
||||
# post processing of the array follows further below...
|
||||
|
||||
# read the Java version we want to find
|
||||
JVMVersion=$(plist_get_java ':JVMVersion' | xargs)
|
||||
# post processing of the version string follows below...
|
||||
|
||||
|
||||
# read 'Info.plist' file in Oracle style
|
||||
else
|
||||
stub_logger "[PlistStyle] Oracle"
|
||||
|
||||
# set Working Directory and Java and Resources folder
|
||||
JavaFolder="${OracleJavaFolder}"
|
||||
ResourcesFolder="${OracleResourcesFolder}"
|
||||
WorkingDirectory="${OracleJavaFolder}"
|
||||
|
||||
# set expandable variables
|
||||
APP_ROOT="${AppPackageFolder}"
|
||||
APP_PACKAGE="${AppPackageFolder}"
|
||||
JAVAROOT="${OracleJavaFolder}"
|
||||
USER_HOME="$HOME"
|
||||
|
||||
# read the MainClass name
|
||||
JVMMainClass="$(plist_get ':JVMMainClassName')"
|
||||
|
||||
# read the SplashFile name
|
||||
JVMSplashFile=$(plist_get ':JVMSplashFile')
|
||||
|
||||
# read the JVM Options as an array and retain spaces
|
||||
IFS=$'\t\n'
|
||||
JVMOptions=($(plist_get ':JVMOptions' | grep " " | sed 's/^ *//g'))
|
||||
unset IFS
|
||||
# post processing of the array follows further below...
|
||||
|
||||
# read the ClassPath in either Array or String style
|
||||
JVMClassPath_RAW=$(plist_get ':JVMClassPath')
|
||||
if [[ $JVMClassPath_RAW == *Array* ]] ; then
|
||||
JVMClassPath=.$(plist_get ':JVMClassPath' | grep " " | sed 's/^ */:/g' | tr -d '\n' | xargs)
|
||||
# expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME
|
||||
JVMClassPath=$(eval echo "${JVMClassPath}")
|
||||
|
||||
elif [[ ! -z ${JVMClassPath_RAW} ]] ; then
|
||||
JVMClassPath=${JVMClassPath_RAW}
|
||||
# expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME
|
||||
JVMClassPath=$(eval echo "${JVMClassPath}")
|
||||
|
||||
else
|
||||
#default: fallback to OracleJavaFolder
|
||||
JVMClassPath="${JavaFolder}/*"
|
||||
# Do NOT expand the default 'AppName.app/Contents/Java/*' classpath (#42)
|
||||
fi
|
||||
|
||||
# read the JVM Default Options by parsing the :JVMDefaultOptions <dict>
|
||||
# and pulling all <string> values starting with a dash (-)
|
||||
JVMDefaultOptions=$(plist_get ':JVMDefaultOptions' | grep -o " \-.*" | tr -d '\n' | xargs)
|
||||
# expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME (#99)
|
||||
JVMDefaultOptions=$(eval echo "${JVMDefaultOptions}")
|
||||
|
||||
# read the Main Arguments from JVMArguments key as an array and retain spaces (see #46 for naming details)
|
||||
IFS=$'\t\n'
|
||||
MainArgs=($(xargs -n1 <<<$(plist_get ':JVMArguments' | tr -d '\n' | sed -E 's/Array \{ *(.*) *\}/\1/g' | sed 's/ */ /g')))
|
||||
unset IFS
|
||||
# post processing of the array follows further below...
|
||||
|
||||
# read the Java version we want to find
|
||||
JVMVersion=$(plist_get ':JVMVersion' | xargs)
|
||||
# post processing of the version string follows below...
|
||||
fi
|
||||
|
||||
|
||||
# (#75) check for undefined icons or icon names without .icns extension and prepare
|
||||
# an osascript statement for those cases when the icon can be shown in the dialog
|
||||
DialogWithIcon=""
|
||||
if [ ! -z ${CFBundleIconFile} ]; then
|
||||
if [[ ${CFBundleIconFile} == *.icns ]] && [[ -f "${ResourcesFolder}/${CFBundleIconFile}" ]] ; then
|
||||
DialogWithIcon=" with icon path to resource \"${CFBundleIconFile}\" in bundle (path to me)"
|
||||
elif [[ ${CFBundleIconFile} != *.icns ]] && [[ -f "${ResourcesFolder}/${CFBundleIconFile}.icns" ]] ; then
|
||||
CFBundleIconFile+=".icns"
|
||||
DialogWithIcon=" with icon path to resource \"${CFBundleIconFile}\" in bundle (path to me)"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# JVMVersion: post processing and optional splitting
|
||||
if [[ ${JVMVersion} == *";"* ]]; then
|
||||
minMaxArray=(${JVMVersion//;/ })
|
||||
JVMVersion=${minMaxArray[0]//+}
|
||||
JVMMaxVersion=${minMaxArray[1]//+}
|
||||
fi
|
||||
stub_logger "[JavaRequirement] JVM minimum version: ${JVMVersion}"
|
||||
stub_logger "[JavaRequirement] JVM maximum version: ${JVMMaxVersion}"
|
||||
|
||||
# MainArgs: expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME
|
||||
MainArgsArr=()
|
||||
for i in "${MainArgs[@]}"
|
||||
do
|
||||
MainArgsArr+=("$(eval echo "$i")")
|
||||
done
|
||||
|
||||
# JVMOptions: expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME
|
||||
JVMOptionsArr=()
|
||||
for i in "${JVMOptions[@]}"
|
||||
do
|
||||
JVMOptionsArr+=("$(eval echo "$i")")
|
||||
done
|
||||
|
||||
|
||||
# internationalized messages
|
||||
############################################
|
||||
|
||||
# supported languages / available translations
|
||||
stubLanguages="^(fr|de|zh|es|en)-"
|
||||
|
||||
# read user preferred languages as defined in macOS System Preferences (#101)
|
||||
stub_logger '[LanguageSearch] Checking preferred languages in macOS System Preferences...'
|
||||
appleLanguages=($(defaults read -g AppleLanguages | grep '\s"' | tr -d ',' | xargs))
|
||||
stub_logger "[LanguageSearch] ... found [${appleLanguages[*]}]"
|
||||
|
||||
language=""
|
||||
for i in "${appleLanguages[@]}"
|
||||
do
|
||||
langValue="${i%-*}"
|
||||
if [[ "$i" =~ $stubLanguages ]]; then
|
||||
stub_logger "[LanguageSearch] ... selected '$i' ('$langValue') as the default language for the launcher stub"
|
||||
language=${langValue}
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ -z "${language}" ]; then
|
||||
language="en"
|
||||
stub_logger "[LanguageSearch] ... selected fallback 'en' as the default language for the launcher stub"
|
||||
fi
|
||||
stub_logger "[Language] $language"
|
||||
|
||||
|
||||
case "${language}" in
|
||||
# French
|
||||
fr)
|
||||
MSG_ERROR_LAUNCHING="ERREUR au lancement de '${CFBundleName}'."
|
||||
MSG_MISSING_MAINCLASS="'MainClass' n'est pas spécifié.\nL'application Java ne peut pas être lancée."
|
||||
MSG_JVMVERSION_REQ_INVALID="La syntaxe de la version de Java demandée est invalide: %s\nVeuillez contacter le développeur de l'application."
|
||||
MSG_NO_SUITABLE_JAVA="La version de Java installée sur votre système ne convient pas.\nCe programme nécessite Java %s"
|
||||
MSG_JAVA_VERSION_OR_LATER="ou ultérieur"
|
||||
MSG_JAVA_VERSION_LATEST="(dernière mise à jour)"
|
||||
MSG_JAVA_VERSION_MAX="à %s"
|
||||
MSG_NO_SUITABLE_JAVA_CHECK="Merci de bien vouloir installer la version de Java requise."
|
||||
MSG_INSTALL_JAVA="Java doit être installé sur votre système.\nRendez-vous sur java.com et suivez les instructions d'installation..."
|
||||
MSG_LATER="Plus tard"
|
||||
MSG_VISIT_JAVA_DOT_COM="Java by Oracle"
|
||||
MSG_VISIT_ADOPTIUM="Java by Adoptium"
|
||||
;;
|
||||
|
||||
# German
|
||||
de)
|
||||
MSG_ERROR_LAUNCHING="FEHLER beim Starten von '${CFBundleName}'."
|
||||
MSG_MISSING_MAINCLASS="Die 'MainClass' ist nicht spezifiziert!\nDie Java-Anwendung kann nicht gestartet werden!"
|
||||
MSG_JVMVERSION_REQ_INVALID="Die Syntax der angeforderten Java-Version ist ungültig: %s\nBitte kontaktieren Sie den Entwickler der App."
|
||||
MSG_NO_SUITABLE_JAVA="Es wurde keine passende Java-Version auf Ihrem System gefunden!\nDieses Programm benötigt Java %s"
|
||||
MSG_JAVA_VERSION_OR_LATER="oder neuer"
|
||||
MSG_JAVA_VERSION_LATEST="(neuste Unterversion)"
|
||||
MSG_JAVA_VERSION_MAX="bis %s"
|
||||
MSG_NO_SUITABLE_JAVA_CHECK="Stellen Sie sicher, dass die angeforderte Java-Version installiert ist."
|
||||
MSG_INSTALL_JAVA="Auf Ihrem System muss die 'Java'-Software installiert sein.\nBesuchen Sie java.com für weitere Installationshinweise."
|
||||
MSG_LATER="Später"
|
||||
MSG_VISIT_JAVA_DOT_COM="Java von Oracle"
|
||||
MSG_VISIT_ADOPTIUM="Java von Adoptium"
|
||||
;;
|
||||
|
||||
# Simplified Chinese
|
||||
zh)
|
||||
MSG_ERROR_LAUNCHING="无法启动 '${CFBundleName}'."
|
||||
MSG_MISSING_MAINCLASS="没有指定 'MainClass'!\nJava程序无法启动!"
|
||||
MSG_JVMVERSION_REQ_INVALID="Java版本参数语法错误: %s\n请联系该应用的开发者。"
|
||||
MSG_NO_SUITABLE_JAVA="没有在系统中找到合适的Java版本!\n必须安装Java %s才能够使用该程序!"
|
||||
MSG_JAVA_VERSION_OR_LATER="及以上版本"
|
||||
MSG_JAVA_VERSION_LATEST="(最新版本)"
|
||||
MSG_JAVA_VERSION_MAX="最高为 %s"
|
||||
MSG_NO_SUITABLE_JAVA_CHECK="请确保系统中安装了所需的Java版本"
|
||||
MSG_INSTALL_JAVA="你需要在Mac中安装Java运行环境!\n访问 java.com 了解如何安装。"
|
||||
MSG_LATER="稍后"
|
||||
MSG_VISIT_JAVA_DOT_COM="Java by Oracle"
|
||||
MSG_VISIT_ADOPTIUM="Java by Adoptium"
|
||||
;;
|
||||
|
||||
# Spanish
|
||||
es)
|
||||
MSG_ERROR_LAUNCHING="ERROR iniciando '${CFBundleName}'."
|
||||
MSG_MISSING_MAINCLASS="¡'MainClass' no especificada!\n¡La aplicación Java no puede iniciarse!"
|
||||
MSG_JVMVERSION_REQ_INVALID="La sintaxis de la versión Java requerida no es válida: %s\nPor favor, contacte con el desarrollador de la aplicación."
|
||||
MSG_NO_SUITABLE_JAVA="¡No se encontró una versión de Java adecuada en su sistema!\nEste programa requiere Java %s"
|
||||
MSG_JAVA_VERSION_OR_LATER="o posterior"
|
||||
MSG_JAVA_VERSION_LATEST="(ultima actualización)"
|
||||
MSG_JAVA_VERSION_MAX="superior a %s"
|
||||
MSG_NO_SUITABLE_JAVA_CHECK="Asegúrese de instalar la versión Java requerida."
|
||||
MSG_INSTALL_JAVA="¡Necesita tener JAVA instalado en su Mac!\nVisite java.com para consultar las instrucciones para su instalación..."
|
||||
MSG_LATER="Más tarde"
|
||||
MSG_VISIT_JAVA_DOT_COM="Java de Oracle"
|
||||
MSG_VISIT_ADOPTIUM="Java de Adoptium"
|
||||
;;
|
||||
|
||||
# English | default
|
||||
en|*)
|
||||
MSG_ERROR_LAUNCHING="ERROR launching '${CFBundleName}'."
|
||||
MSG_MISSING_MAINCLASS="'MainClass' isn't specified!\nJava application cannot be started!"
|
||||
MSG_JVMVERSION_REQ_INVALID="The syntax of the required Java version is invalid: %s\nPlease contact the App developer."
|
||||
MSG_NO_SUITABLE_JAVA="No suitable Java version found on your system!\nThis program requires Java %s"
|
||||
MSG_JAVA_VERSION_OR_LATER="or later"
|
||||
MSG_JAVA_VERSION_LATEST="(latest update)"
|
||||
MSG_JAVA_VERSION_MAX="up to %s"
|
||||
MSG_NO_SUITABLE_JAVA_CHECK="Make sure you install the required Java version."
|
||||
MSG_INSTALL_JAVA="You need to have JAVA installed on your Mac!\nVisit java.com for installation instructions..."
|
||||
MSG_LATER="Later"
|
||||
MSG_VISIT_JAVA_DOT_COM="Java by Oracle"
|
||||
MSG_VISIT_ADOPTIUM="Java by Adoptium"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
|
||||
# function 'get_java_version_from_cmd()'
|
||||
#
|
||||
# returns Java version string from 'java -version' command
|
||||
# works for both old (1.8) and new (9) version schema
|
||||
#
|
||||
# @param1 path to a java JVM executable
|
||||
# @return the Java version number as displayed in 'java -version' command
|
||||
################################################################################
|
||||
function get_java_version_from_cmd() {
|
||||
# second sed command strips " and -ea from the version string
|
||||
echo $("$1" -version 2>&1 | awk '/version/{print $3}' | sed -E 's/"//g;s/-ea//g')
|
||||
}
|
||||
|
||||
|
||||
# function 'extract_java_major_version()'
|
||||
#
|
||||
# extract Java major version from a version string
|
||||
#
|
||||
# @param1 a Java version number ('1.8.0_45') or requirement string ('1.8+')
|
||||
# @return the major version (e.g. '7', '8' or '9', etc.)
|
||||
################################################################################
|
||||
function extract_java_major_version() {
|
||||
echo $(echo "$1" | sed -E 's/^1\.//;s/^([0-9]+)(-ea|(\.[0-9_.]{1,7})?)(-b[0-9]+-[0-9]+)?[+*]?$/\1/')
|
||||
}
|
||||
|
||||
|
||||
# function 'get_comparable_java_version()'
|
||||
#
|
||||
# return comparable version for a Java version number or requirement string
|
||||
#
|
||||
# @param1 a Java version number ('1.8.0_45') or requirement string ('1.8+')
|
||||
# @return an 8 digit numeral ('1.8.0_45'->'08000045'; '9.1.13'->'09001013')
|
||||
################################################################################
|
||||
function get_comparable_java_version() {
|
||||
# cleaning: 1) remove leading '1.'; 2) remove build string (e.g. '-b14-468'); 3) remove 'a-Z' and '-*+' (e.g. '-ea'); 4) replace '_' with '.'
|
||||
local cleaned=$(echo "$1" | sed -E 's/^1\.//g;s/-b[0-9]+-[0-9]+$//g;s/[a-zA-Z+*\-]//g;s/_/./g')
|
||||
# splitting at '.' into an array
|
||||
local arr=( ${cleaned//./ } )
|
||||
# echo a string with left padded version numbers
|
||||
echo "$(printf '%02s' ${arr[0]})$(printf '%03s' ${arr[1]})$(printf '%03s' ${arr[2]})"
|
||||
}
|
||||
|
||||
|
||||
# function 'is_valid_requirement_pattern()'
|
||||
#
|
||||
# check whether the Java requirement is a valid requirement pattern
|
||||
#
|
||||
# supported requirements are for example:
|
||||
# - 1.6 requires Java 6 (any update) [1.6, 1.6.0_45, 1.6.0_88]
|
||||
# - 1.6* requires Java 6 (any update) [1.6, 1.6.0_45, 1.6.0_88]
|
||||
# - 1.6+ requires Java 6 or higher [1.6, 1.6.0_45, 1.8, 9, etc.]
|
||||
# - 1.6.0 requires Java 6 (any update) [1.6, 1.6.0_45, 1.6.0_88]
|
||||
# - 1.6.0_45 requires Java 6u45 [1.6.0_45]
|
||||
# - 1.6.0_45+ requires Java 6u45 or higher [1.6.0_45, 1.6.0_88, 1.8, etc.]
|
||||
# - 9 requires Java 9 (any update) [9.0.*, 9.1, 9.3, etc.]
|
||||
# - 9* requires Java 9 (any update) [9.0.*, 9.1, 9.3, etc.]
|
||||
# - 9+ requires Java 9 or higher [9.0, 9.1, 10, etc.]
|
||||
# - 9.1 requires Java 9.1 (any update) [9.1.*, 9.1.2, 9.1.13, etc.]
|
||||
# - 9.1* requires Java 9.1 (any update) [9.1.*, 9.1.2, 9.1.13, etc.]
|
||||
# - 9.1+ requires Java 9.1 or higher [9.1, 9.2, 10, etc.]
|
||||
# - 9.1.3 requires Java 9.1.3 [9.1.3]
|
||||
# - 9.1.3* requires Java 9.1.3 (any update) [9.1.3]
|
||||
# - 9.1.3+ requires Java 9.1.3 or higher [9.1.3, 9.1.4, 9.2.*, 10, etc.]
|
||||
# - 10-ea requires Java 10 (early access release)
|
||||
#
|
||||
# unsupported requirement patterns are for example:
|
||||
# - 1.2, 1.3, 1.9 Java 2, 3 are not supported
|
||||
# - 1.9 Java 9 introduced a new versioning scheme
|
||||
# - 6u45 known versioning syntax, but unsupported
|
||||
# - 9-ea*, 9-ea+ early access releases paired with */+
|
||||
# - 9., 9.*, 9.+ version ending with a .
|
||||
# - 9.1., 9.1.*, 9.1.+ version ending with a .
|
||||
# - 9.3.5.6 4 part version number is unsupported
|
||||
#
|
||||
# @param1 a Java requirement string ('1.8+')
|
||||
# @return boolean exit code: 0 (is valid), 1 (is not valid)
|
||||
################################################################################
|
||||
function is_valid_requirement_pattern() {
|
||||
local java_req=$1
|
||||
java8pattern='1\.[4-8](\.[0-9]+)?(\.0_[0-9]+)?[*+]?'
|
||||
java9pattern='(9|1[0-9])(-ea|[*+]|(\.[0-9]+){1,2}[*+]?)?'
|
||||
# test matches either old Java versioning scheme (up to 1.8) or new scheme (starting with 9)
|
||||
if [[ ${java_req} =~ ^(${java8pattern}|${java9pattern})$ ]]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
# determine which JVM to use
|
||||
############################################
|
||||
|
||||
# default Apple JRE plugin path (< 1.6)
|
||||
apple_jre_plugin="/Library/Java/Home/bin/java"
|
||||
apple_jre_version=$(get_java_version_from_cmd "${apple_jre_plugin}")
|
||||
# default Oracle JRE plugin path (>= 1.7)
|
||||
oracle_jre_plugin="/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java"
|
||||
oracle_jre_version=$(get_java_version_from_cmd "${oracle_jre_plugin}")
|
||||
|
||||
|
||||
# first check system variable "$JAVA_HOME" -> has precedence over any other System JVM
|
||||
stub_logger '[JavaSearch] Checking for $JAVA_HOME ...'
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
stub_logger "[JavaSearch] ... found JAVA_HOME with value $JAVA_HOME"
|
||||
|
||||
# PR 26: Allow specifying "$JAVA_HOME" relative to "$AppPackageFolder"
|
||||
# which allows for bundling a custom version of Java inside your app!
|
||||
if [[ $JAVA_HOME == /* ]] ; then
|
||||
# if "$JAVA_HOME" starts with a Slash it's an absolute path
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
stub_logger "[JavaSearch] ... parsing JAVA_HOME as absolute path to the executable '$JAVACMD'"
|
||||
else
|
||||
# otherwise it's a relative path to "$AppPackageFolder"
|
||||
JAVACMD="$AppPackageFolder/$JAVA_HOME/bin/java"
|
||||
stub_logger "[JavaSearch] ... parsing JAVA_HOME as relative path inside the App bundle to the executable '$JAVACMD'"
|
||||
fi
|
||||
JAVACMD_version=$(get_comparable_java_version $(get_java_version_from_cmd "${JAVACMD}"))
|
||||
else
|
||||
stub_logger "[JavaSearch] ... haven't found JAVA_HOME"
|
||||
fi
|
||||
|
||||
|
||||
# check for any other or a specific Java version
|
||||
# also if $JAVA_HOME exists but isn't executable
|
||||
if [ -z "${JAVACMD}" ] || [ ! -x "${JAVACMD}" ] ; then
|
||||
|
||||
# add a warning in the syslog if JAVA_HOME is not executable or not found (#100)
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
stub_logger "[JavaSearch] ... but no 'java' executable was found at the JAVA_HOME location!"
|
||||
fi
|
||||
|
||||
stub_logger "[JavaSearch] Searching for JavaVirtualMachines on the system ..."
|
||||
# reset variables
|
||||
JAVACMD=""
|
||||
JAVACMD_version=""
|
||||
|
||||
# first check whether JVMVersion string is a valid requirement string
|
||||
if [ ! -z "${JVMVersion}" ] && ! is_valid_requirement_pattern ${JVMVersion} ; then
|
||||
MSG_JVMVERSION_REQ_INVALID_EXPANDED=$(printf "${MSG_JVMVERSION_REQ_INVALID}" "${JVMVersion}")
|
||||
# log exit cause
|
||||
stub_logger "[EXIT 4] ${MSG_JVMVERSION_REQ_INVALID_EXPANDED}"
|
||||
# display error message with AppleScript
|
||||
osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_JVMVERSION_REQ_INVALID_EXPANDED}\" with title \"${CFBundleName}\" buttons {\" OK \"} default button 1${DialogWithIcon}"
|
||||
# exit with error
|
||||
exit 4
|
||||
fi
|
||||
# then check whether JVMMaxVersion string is a valid requirement string
|
||||
if [ ! -z "${JVMMaxVersion}" ] && ! is_valid_requirement_pattern ${JVMMaxVersion} ; then
|
||||
MSG_JVMVERSION_REQ_INVALID_EXPANDED=$(printf "${MSG_JVMVERSION_REQ_INVALID}" "${JVMMaxVersion}")
|
||||
# log exit cause
|
||||
stub_logger "[EXIT 5] ${MSG_JVMVERSION_REQ_INVALID_EXPANDED}"
|
||||
# display error message with AppleScript
|
||||
osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_JVMVERSION_REQ_INVALID_EXPANDED}\" with title \"${CFBundleName}\" buttons {\" OK \"} default button 1${DialogWithIcon}"
|
||||
# exit with error
|
||||
exit 5
|
||||
fi
|
||||
|
||||
|
||||
# find installed JavaVirtualMachines (JDK + JRE)
|
||||
allJVMs=()
|
||||
|
||||
# read JDK's from '/usr/libexec/java_home --xml' command with PlistBuddy and a custom Dict iterator
|
||||
# idea: https://stackoverflow.com/a/14085460/1128689 and https://scriptingosx.com/2018/07/parsing-dscl-output-in-scripts/
|
||||
javaXml=$(/usr/libexec/java_home --xml)
|
||||
javaCounter=$(/usr/libexec/PlistBuddy -c "Print" /dev/stdin <<< $javaXml | grep "Dict" | wc -l | tr -d ' ')
|
||||
|
||||
# iterate over all Dict entries
|
||||
# but only if there are any JVMs at all (#93)
|
||||
if [ "$javaCounter" -gt "0" ] ; then
|
||||
for idx in $(seq 0 $((javaCounter - 1)))
|
||||
do
|
||||
version=$(/usr/libexec/PlistBuddy -c "print :$idx:JVMVersion" /dev/stdin <<< $javaXml)
|
||||
path=$(/usr/libexec/PlistBuddy -c "print :$idx:JVMHomePath" /dev/stdin <<< $javaXml)
|
||||
path+="/bin/java"
|
||||
allJVMs+=("$version:$path")
|
||||
done
|
||||
# unset for loop variables
|
||||
unset version path
|
||||
fi
|
||||
|
||||
# add SDKMAN! java versions (#95)
|
||||
if [ -d ~/.sdkman/candidates/java/ ] ; then
|
||||
for sdkjdk in ~/.sdkman/candidates/java/*/
|
||||
do
|
||||
if [[ ${sdkjdk} =~ /current/$ ]] ; then
|
||||
continue
|
||||
fi
|
||||
|
||||
sdkjdkcmd="${sdkjdk}bin/java"
|
||||
version=$(get_java_version_from_cmd "${sdkjdkcmd}")
|
||||
allJVMs+=("$version:$sdkjdkcmd")
|
||||
done
|
||||
# unset for loop variables
|
||||
unset version
|
||||
fi
|
||||
|
||||
# add Apple JRE if available
|
||||
if [ -x "${apple_jre_plugin}" ] ; then
|
||||
allJVMs+=("$apple_jre_version:$apple_jre_plugin")
|
||||
fi
|
||||
|
||||
# add Oracle JRE if available
|
||||
if [ -x "${oracle_jre_plugin}" ] ; then
|
||||
allJVMs+=("$oracle_jre_version:$oracle_jre_plugin")
|
||||
fi
|
||||
|
||||
# debug output
|
||||
for i in "${allJVMs[@]}"
|
||||
do
|
||||
stub_logger "[JavaSearch] ... found JVM: $i"
|
||||
done
|
||||
|
||||
|
||||
# determine JVMs matching the min/max version requirement
|
||||
|
||||
stub_logger "[JavaSearch] Filtering the result list for JVMs matching the min/max version requirement ..."
|
||||
|
||||
minC=$(get_comparable_java_version ${JVMVersion})
|
||||
maxC=$(get_comparable_java_version ${JVMMaxVersion})
|
||||
matchingJVMs=()
|
||||
|
||||
for i in "${allJVMs[@]}"
|
||||
do
|
||||
# split JVM string at ':' delimiter to retain spaces in $path substring
|
||||
IFS=: arr=($i) ; unset IFS
|
||||
# [0] JVM version number
|
||||
ver=${arr[0]}
|
||||
# comparable JVM version number
|
||||
comp=$(get_comparable_java_version $ver)
|
||||
# [1] JVM path
|
||||
path="${arr[1]}"
|
||||
# construct string item for adding to the "matchingJVMs" array
|
||||
item="$comp:$ver:$path"
|
||||
|
||||
# pre-requisite: current version number needs to be greater than min version number
|
||||
if [ "$comp" -ge "$minC" ] ; then
|
||||
|
||||
# perform max version checks if max version requirement is present
|
||||
if [ ! -z ${JVMMaxVersion} ] ; then
|
||||
|
||||
# max version requirement ends with '*' modifier
|
||||
if [[ ${JVMMaxVersion} == *\* ]] ; then
|
||||
|
||||
# use the '*' modifier from the max version string as wildcard for a 'starts with' comparison
|
||||
# and check whether the current version number starts with the max version wildcard string
|
||||
if [[ ${ver} == ${JVMMaxVersion} ]]; then
|
||||
matchingJVMs+=("$item")
|
||||
|
||||
# or whether the current comparable version is lower than the comparable max version
|
||||
elif [ "$comp" -le "$maxC" ] ; then
|
||||
matchingJVMs+=("$item")
|
||||
fi
|
||||
|
||||
# max version requirement ends with '+' modifier -> always add this version if it's greater than $min
|
||||
# because a max requirement with + modifier doesn't make sense
|
||||
elif [[ ${JVMMaxVersion} == *+ ]] ; then
|
||||
matchingJVMs+=("$item")
|
||||
|
||||
# matches 6 zeros at the end of the max version string (e.g. for 1.8, 9)
|
||||
# -> then the max version string should be treated like with a '*' modifier at the end
|
||||
#elif [[ ${maxC} =~ ^[0-9]{2}0{6}$ ]] && [ "$comp" -le $(( ${maxC#0} + 999 )) ] ; then
|
||||
# matchingJVMs+=("$item")
|
||||
|
||||
# matches 3 zeros at the end of the max version string (e.g. for 9.1, 10.3)
|
||||
# -> then the max version string should be treated like with a '*' modifier at the end
|
||||
#elif [[ ${maxC} =~ ^[0-9]{5}0{3}$ ]] && [ "$comp" -le "${maxC}" ] ; then
|
||||
# matchingJVMs+=("$item")
|
||||
|
||||
# matches standard requirements without modifier
|
||||
elif [ "$comp" -le "$maxC" ]; then
|
||||
matchingJVMs+=("$item")
|
||||
fi
|
||||
|
||||
# no max version requirement:
|
||||
|
||||
# min version requirement ends with '+' modifier
|
||||
# -> always add the current version because it's greater than $min
|
||||
elif [[ ${JVMVersion} == *+ ]] ; then
|
||||
matchingJVMs+=("$item")
|
||||
|
||||
# min version requirement ends with '*' modifier
|
||||
# -> use the '*' modifier from the min version string as wildcard for a 'starts with' comparison
|
||||
# and check whether the current version number starts with the min version wildcard string
|
||||
elif [[ ${JVMVersion} == *\* ]] ; then
|
||||
if [[ ${ver} == ${JVMVersion} ]] ; then
|
||||
matchingJVMs+=("$item")
|
||||
fi
|
||||
|
||||
# compare the min version against the current version with an additional * wildcard for a 'starts with' comparison
|
||||
# -> e.g. add 1.8.0_44 when the requirement is 1.8
|
||||
elif [[ ${ver} == ${JVMVersion}* ]] ; then
|
||||
matchingJVMs+=("$item")
|
||||
fi
|
||||
fi
|
||||
done
|
||||
# unset for loop variables
|
||||
unset arr ver comp path item
|
||||
|
||||
# debug output
|
||||
for i in "${matchingJVMs[@]}"
|
||||
do
|
||||
stub_logger "[JavaSearch] ... matches all requirements: $i"
|
||||
done
|
||||
|
||||
|
||||
# sort the matching JavaVirtualMachines by version number
|
||||
# https://stackoverflow.com/a/11789688/1128689
|
||||
IFS=$'\n' matchingJVMs=($(sort -nr <<<"${matchingJVMs[*]}"))
|
||||
unset IFS
|
||||
|
||||
|
||||
# get the highest matching JVM
|
||||
for ((i = 0; i < ${#matchingJVMs[@]}; i++));
|
||||
do
|
||||
# split JVM string at ':' delimiter to retain spaces in $path substring
|
||||
IFS=: arr=(${matchingJVMs[$i]}) ; unset IFS
|
||||
# [0] comparable JVM version number
|
||||
comp=${arr[0]}
|
||||
# [1] JVM version number
|
||||
ver=${arr[1]}
|
||||
# [2] JVM path
|
||||
path="${arr[2]}"
|
||||
|
||||
# use current value as JAVACMD if it's executable
|
||||
if [ -x "$path" ] ; then
|
||||
JAVACMD="$path"
|
||||
JAVACMD_version=$comp
|
||||
break
|
||||
fi
|
||||
done
|
||||
# unset for loop variables
|
||||
unset arr comp ver path
|
||||
fi
|
||||
|
||||
# log the Java Command and the extracted version number
|
||||
stub_logger "[JavaCommand] '$JAVACMD'"
|
||||
stub_logger "[JavaVersion] $(get_java_version_from_cmd "${JAVACMD}")${JAVACMD_version:+ / $JAVACMD_version}"
|
||||
|
||||
# Make sure tabbing mode is disabled for the selected java version
|
||||
|
||||
CFBundleIdentifier=net.java.openjdk.$(get_java_version_from_cmd "${JAVACMD}").java
|
||||
|
||||
if [ x$(defaults read ${CFBundleIdentifier} AppleWindowTabbingMode) != "xnever" ]; then
|
||||
defaults write ${CFBundleIdentifier} AppleWindowTabbingMode never
|
||||
fi
|
||||
|
||||
if [ -z "${JAVACMD}" ] || [ ! -x "${JAVACMD}" ] ; then
|
||||
|
||||
# different error messages when a specific JVM was required
|
||||
if [ ! -z "${JVMVersion}" ] ; then
|
||||
# display human readable java version (#28)
|
||||
java_version_hr=$(echo ${JVMVersion} | sed -E 's/^1\.([0-9+*]+)$/ \1/g' | sed "s/+/ ${MSG_JAVA_VERSION_OR_LATER}/;s/*/ ${MSG_JAVA_VERSION_LATEST}/")
|
||||
MSG_NO_SUITABLE_JAVA_EXPANDED=$(printf "${MSG_NO_SUITABLE_JAVA}" "${java_version_hr}").
|
||||
|
||||
if [ ! -z "${JVMMaxVersion}" ] ; then
|
||||
java_version_hr=$(extract_java_major_version ${JVMVersion})
|
||||
java_version_max_hr=$(echo ${JVMMaxVersion} | sed -E 's/^1\.([0-9+*]+)$/ \1/g' | sed "s/+//;s/*/ ${MSG_JAVA_VERSION_LATEST}/")
|
||||
MSG_NO_SUITABLE_JAVA_EXPANDED="$(printf "${MSG_NO_SUITABLE_JAVA}" "${java_version_hr}") $(printf "${MSG_JAVA_VERSION_MAX}" "${java_version_max_hr}")"
|
||||
fi
|
||||
|
||||
# log exit cause
|
||||
stub_logger "[EXIT 3] ${MSG_NO_SUITABLE_JAVA_EXPANDED}"
|
||||
|
||||
# display error message with AppleScript
|
||||
osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_NO_SUITABLE_JAVA_EXPANDED}\n${MSG_NO_SUITABLE_JAVA_CHECK}\" with title \"${CFBundleName}\" buttons {\" OK \", \"${MSG_VISIT_JAVA_DOT_COM}\", \"${MSG_VISIT_ADOPTIUM}\"} default button 1${DialogWithIcon}" \
|
||||
-e "set response to button returned of the result" \
|
||||
-e "if response is \"${MSG_VISIT_JAVA_DOT_COM}\" then open location \"https://www.java.com/download/\"" \
|
||||
-e "if response is \"${MSG_VISIT_ADOPTIUM}\" then open location \"https://adoptium.net/releases.html\""
|
||||
# exit with error
|
||||
exit 3
|
||||
|
||||
else
|
||||
# log exit cause
|
||||
stub_logger "[EXIT 1] ${MSG_ERROR_LAUNCHING}"
|
||||
# display error message with AppleScript
|
||||
osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_INSTALL_JAVA}\" with title \"${CFBundleName}\" buttons {\"${MSG_LATER}\", \"${MSG_VISIT_JAVA_DOT_COM}\", \"${MSG_VISIT_ADOPTIUM}\"} default button 1${DialogWithIcon}" \
|
||||
-e "set response to button returned of the result" \
|
||||
-e "if response is \"${MSG_VISIT_JAVA_DOT_COM}\" then open location \"https://www.java.com/download/\"" \
|
||||
-e "if response is \"${MSG_VISIT_ADOPTIUM}\" then open location \"https://adoptium.net/releases.html\""
|
||||
# exit with error
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# MainClass check
|
||||
############################################
|
||||
|
||||
if [ -z "${JVMMainClass}" ]; then
|
||||
# log exit cause
|
||||
stub_logger "[EXIT 2] ${MSG_MISSING_MAINCLASS}"
|
||||
# display error message with AppleScript
|
||||
osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_MISSING_MAINCLASS}\" with title \"${CFBundleName}\" buttons {\" OK \"} default button 1${DialogWithIcon}"
|
||||
# exit with error
|
||||
exit 2
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# execute $JAVACMD and do some preparation
|
||||
############################################
|
||||
|
||||
# enable drag&drop to the dock icon
|
||||
export CFProcessPath="$0"
|
||||
|
||||
# remove Apples ProcessSerialNumber from passthru arguments (#39)
|
||||
if [[ "$*" == -psn* ]] ; then
|
||||
ArgsPassthru=()
|
||||
else
|
||||
ArgsPassthru=("$@")
|
||||
fi
|
||||
|
||||
# change to Working Directory based upon Apple/Oracle Plist info
|
||||
cd "${WorkingDirectory}" || exit 13
|
||||
stub_logger "[WorkingDirectory] ${WorkingDirectory}"
|
||||
|
||||
# execute Java and set
|
||||
# - classpath
|
||||
# - splash image
|
||||
# - dock icon
|
||||
# - app name
|
||||
# - JVM options / properties (-D)
|
||||
# - JVM default options (-X)
|
||||
# - main class
|
||||
# - main class arguments
|
||||
# - passthrough arguments from Terminal or Drag'n'Drop to Finder icon
|
||||
stub_logger "[Exec] \"$JAVACMD\" -cp \"${JVMClassPath}\" ${JVMSplashFile:+ -splash:\"${ResourcesFolder}/${JVMSplashFile}\"} -Xdock:icon=\"${ResourcesFolder}/${CFBundleIconFile}\" -Xdock:name=\"${CFBundleName}\" ${JVMOptionsArr:+$(printf "'%s' " "${JVMOptionsArr[@]}") }${JVMDefaultOptions:+$JVMDefaultOptions }${JVMMainClass}${MainArgsArr:+ $(printf "'%s' " "${MainArgsArr[@]}")}${ArgsPassthru:+ $(printf "'%s' " "${ArgsPassthru[@]}")}"
|
||||
exec "${JAVACMD}" \
|
||||
-Djava.library.path="${AppleJavaFolder}" \
|
||||
-cp "${JVMClassPath}" \
|
||||
${JVMSplashFile:+ -splash:"${ResourcesFolder}/${JVMSplashFile}"} \
|
||||
-Xdock:icon="${ResourcesFolder}/${CFBundleIconFile}" \
|
||||
-Xdock:name="${CFBundleName}" \
|
||||
${JVMOptionsArr:+"${JVMOptionsArr[@]}" }\
|
||||
${JVMDefaultOptions:+$JVMDefaultOptions }\
|
||||
"${JVMMainClass}"\
|
||||
${MainArgsArr:+ "${MainArgsArr[@]}"}\
|
||||
${ArgsPassthru:+ "${ArgsPassthru[@]}"}
|
1
altosui/AltosUI.app/Contents/PkgInfo
Normal file
1
altosui/AltosUI.app/Contents/PkgInfo
Normal file
@@ -0,0 +1 @@
|
||||
APPLAM.O
|
651
altosui/AltosUI.java
Normal file
651
altosui/AltosUI.java
Normal file
@@ -0,0 +1,651 @@
|
||||
/*
|
||||
* Copyright © 2010 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* 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 altosui;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import java.io.*;
|
||||
import java.util.concurrent.*;
|
||||
import org.altusmetrum.altoslib_14.*;
|
||||
import org.altusmetrum.altosuilib_14.*;
|
||||
|
||||
public class AltosUI extends AltosUIFrame implements AltosEepromGrapher {
|
||||
public AltosVoice voice = new AltosVoice();
|
||||
|
||||
public static boolean load_library(Frame frame) {
|
||||
if (!Altos.load_library()) {
|
||||
JOptionPane.showMessageDialog(frame,
|
||||
String.format("No AltOS library in \"%s\"",
|
||||
System.getProperty("java.library.path","<undefined>")),
|
||||
"Cannot load device access library",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void telemetry_window(AltosDevice device) {
|
||||
try {
|
||||
AltosFlightReader reader = new AltosTelemetryReader(new AltosSerial(device));
|
||||
if (reader != null)
|
||||
new AltosFlightUI(voice, reader, device.getSerial());
|
||||
} catch (FileNotFoundException ee) {
|
||||
JOptionPane.showMessageDialog(AltosUI.this,
|
||||
ee.getMessage(),
|
||||
String.format ("Cannot open %s", device.toShortString()),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} catch (AltosSerialInUseException si) {
|
||||
JOptionPane.showMessageDialog(AltosUI.this,
|
||||
String.format("Device \"%s\" already in use",
|
||||
device.toShortString()),
|
||||
"Device in use",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} catch (IOException ee) {
|
||||
JOptionPane.showMessageDialog(AltosUI.this,
|
||||
String.format ("Unknown I/O error on %s", device.toShortString()),
|
||||
"Unknown I/O error",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} catch (TimeoutException te) {
|
||||
JOptionPane.showMessageDialog(this,
|
||||
String.format ("Timeout on %s", device.toShortString()),
|
||||
"Timeout error",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} catch (InterruptedException ie) {
|
||||
JOptionPane.showMessageDialog(this,
|
||||
String.format("Interrupted %s", device.toShortString()),
|
||||
"Interrupted exception",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
public void scan_device_selected(AltosDevice device) {
|
||||
telemetry_window(device);
|
||||
}
|
||||
|
||||
Container pane;
|
||||
GridBagLayout gridbag;
|
||||
|
||||
JButton addButton(int x, int y, String label) {
|
||||
GridBagConstraints c;
|
||||
JButton b;
|
||||
|
||||
c = new GridBagConstraints();
|
||||
c.gridx = x; c.gridy = y;
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
c.weightx = 1;
|
||||
c.weighty = 1;
|
||||
b = new JButton(label);
|
||||
|
||||
//Dimension ps = b.getPreferredSize();
|
||||
|
||||
gridbag.setConstraints(b, c);
|
||||
add(b, c);
|
||||
return b;
|
||||
}
|
||||
|
||||
/* OSXAdapter interfaces */
|
||||
public void macosx_file_handler(String path) {
|
||||
process_graph(null, new File(path));
|
||||
}
|
||||
|
||||
public void macosx_quit_handler() {
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
public void macosx_preferences_handler() {
|
||||
ConfigureAltosUI();
|
||||
}
|
||||
|
||||
public AltosUI() {
|
||||
|
||||
load_library(null);
|
||||
|
||||
register_for_macosx_events();
|
||||
|
||||
AltosUIPreferences.set_component(this);
|
||||
|
||||
pane = getContentPane();
|
||||
gridbag = new GridBagLayout();
|
||||
pane.setLayout(gridbag);
|
||||
|
||||
JButton b;
|
||||
|
||||
b = addButton(0, 0, "Monitor Flight");
|
||||
b.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ConnectToDevice();
|
||||
}
|
||||
});
|
||||
b.setToolTipText("Connect to TeleDongle and monitor telemetry");
|
||||
b = addButton(1, 0, "Save Flight Data");
|
||||
b.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
SaveFlightData();
|
||||
}
|
||||
});
|
||||
b.setToolTipText("Download and/or delete flight data from an altimeter");
|
||||
b = addButton(2, 0, "Replay Flight");
|
||||
b.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Replay();
|
||||
}
|
||||
});
|
||||
b.setToolTipText("Watch an old flight in real-time");
|
||||
b = addButton(3, 0, "Graph Data");
|
||||
b.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
GraphData();
|
||||
}
|
||||
});
|
||||
b.setToolTipText("Present flight data in a graph and table of statistics");
|
||||
b = addButton(4, 0, "Export Data");
|
||||
b.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ExportData();
|
||||
}
|
||||
});
|
||||
b.setToolTipText("Convert flight data for a spreadsheet or GoogleEarth");
|
||||
b = addButton(0, 1, "Configure Altimeter");
|
||||
b.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ConfigureTeleMetrum();
|
||||
}
|
||||
});
|
||||
b.setToolTipText("Set flight, storage and communication parameters");
|
||||
b = addButton(1, 1, "Configure AltosUI");
|
||||
b.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ConfigureAltosUI();
|
||||
}
|
||||
});
|
||||
b.setToolTipText("Global AltosUI settings");
|
||||
|
||||
b = addButton(2, 1, "Configure Ground Station");
|
||||
b.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ConfigureTeleDongle();
|
||||
}
|
||||
});
|
||||
|
||||
b = addButton(3, 1, "Flash Image");
|
||||
b.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
FlashImage();
|
||||
}
|
||||
});
|
||||
b.setToolTipText("Replace the firmware in any AltusMetrum product");
|
||||
|
||||
b = addButton(4, 1, "Fire Igniter");
|
||||
b.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
FireIgniter();
|
||||
}
|
||||
});
|
||||
b.setToolTipText("Remote control of igniters for deployment testing");
|
||||
b = addButton(0, 2, "Scan Channels");
|
||||
b.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ScanChannels();
|
||||
}
|
||||
});
|
||||
b.setToolTipText("Find what channel an altimeter is sending telemetry on");
|
||||
b = addButton(1, 2, "Load Maps");
|
||||
b.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LoadMaps();
|
||||
}
|
||||
});
|
||||
b.setToolTipText("Download satellite images for off-line flight monitoring");
|
||||
b = addButton(2, 2, "Monitor Idle");
|
||||
b.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
IdleMonitor();
|
||||
}
|
||||
});
|
||||
b.setToolTipText("Check flight readiness of altimeter in idle mode");
|
||||
|
||||
// b = addButton(3, 2, "Launch Controller");
|
||||
// b.addActionListener(new ActionListener() {
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// LaunchController();
|
||||
// }
|
||||
// });
|
||||
|
||||
b = addButton(4, 2, "Quit");
|
||||
b.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
b.setToolTipText("Close all active windows and terminate AltosUI");
|
||||
|
||||
setTitle("AltOS");
|
||||
|
||||
pane.doLayout();
|
||||
pane.validate();
|
||||
|
||||
doLayout();
|
||||
validate();
|
||||
|
||||
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
|
||||
setLocationByPlatform(false);
|
||||
|
||||
/* Insets aren't set before the window is visible */
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
private void ConnectToDevice() {
|
||||
AltosDevice device = AltosDeviceUIDialog.show(AltosUI.this,
|
||||
Altos.product_basestation);
|
||||
|
||||
if (device != null)
|
||||
telemetry_window(device);
|
||||
}
|
||||
|
||||
void ConfigureCallsign() {
|
||||
String result;
|
||||
result = JOptionPane.showInputDialog(AltosUI.this,
|
||||
"Configure Callsign",
|
||||
AltosUIPreferences.callsign());
|
||||
if (result != null)
|
||||
AltosUIPreferences.set_callsign(result);
|
||||
}
|
||||
|
||||
void ConfigureTeleMetrum() {
|
||||
new AltosConfigFC(AltosUI.this);
|
||||
}
|
||||
|
||||
void ConfigureTeleDongle() {
|
||||
new AltosConfigTD(AltosUI.this);
|
||||
}
|
||||
|
||||
void FlashImage() {
|
||||
AltosFlashUI.show(AltosUI.this);
|
||||
}
|
||||
|
||||
void FireIgniter() {
|
||||
new AltosIgniteUI(AltosUI.this);
|
||||
}
|
||||
|
||||
void ScanChannels() {
|
||||
new AltosScanUI(AltosUI.this, true);
|
||||
}
|
||||
|
||||
void LoadMaps() {
|
||||
new AltosUIMapPreload(AltosUI.this);
|
||||
}
|
||||
|
||||
void LaunchController() {
|
||||
new AltosLaunchUI(AltosUI.this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Replay a flight from telemetry data
|
||||
*/
|
||||
private void Replay() {
|
||||
AltosDataChooser chooser = new AltosDataChooser(
|
||||
AltosUI.this);
|
||||
|
||||
AltosRecordSet set = chooser.runDialog();
|
||||
if (set != null) {
|
||||
AltosReplayReader reader = new AltosReplayReader(set, chooser.file());
|
||||
new AltosFlightUI(voice, reader);
|
||||
}
|
||||
}
|
||||
|
||||
/* Connect to TeleMetrum, either directly or through
|
||||
* a TeleDongle over the packet link
|
||||
*/
|
||||
|
||||
public void graph_flights(AltosEepromList flights) {
|
||||
for (AltosEepromLog flight : flights) {
|
||||
if (flight.graph_selected && flight.file != null) {
|
||||
process_graph(this, flight.file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveFlightData() {
|
||||
new AltosEepromManage(this, this, AltosLib.product_any);
|
||||
}
|
||||
|
||||
private static AltosFlightSeries make_series(AltosRecordSet set) {
|
||||
AltosFlightSeries series = new AltosFlightSeries(set.cal_data());
|
||||
set.capture_series(series);
|
||||
series.finish();
|
||||
return series;
|
||||
}
|
||||
|
||||
/* Load a flight log file and write out a CSV file containing
|
||||
* all of the data in standard units
|
||||
*/
|
||||
|
||||
private void ExportData() {
|
||||
AltosDataChooser chooser;
|
||||
chooser = new AltosDataChooser(this);
|
||||
AltosRecordSet set = chooser.runDialog();
|
||||
if (set == null)
|
||||
return;
|
||||
AltosFlightSeries series = make_series(set);
|
||||
new AltosCSVUI(AltosUI.this, series, chooser.file());
|
||||
}
|
||||
|
||||
private static boolean graph_file(AltosUI altosui, AltosRecordSet set, File file) {
|
||||
if (set == null)
|
||||
return false;
|
||||
if (!set.valid()) {
|
||||
JOptionPane.showMessageDialog(altosui,
|
||||
String.format("Failed to parse file %s", file),
|
||||
"Graph Failed",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
new AltosGraphUI(set, file);
|
||||
return true;
|
||||
} catch (InterruptedException ie) {
|
||||
} catch (IOException ie) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Load a flight log CSV file and display a pretty graph.
|
||||
*/
|
||||
|
||||
private void GraphData() {
|
||||
AltosDataChooser chooser;
|
||||
chooser = new AltosDataChooser(this);
|
||||
AltosRecordSet set = chooser.runDialog();
|
||||
graph_file(this, set, chooser.file());
|
||||
}
|
||||
|
||||
private void ConfigureAltosUI() {
|
||||
new AltosConfigureUI(AltosUI.this, voice);
|
||||
}
|
||||
|
||||
private void IdleMonitor() {
|
||||
try {
|
||||
new AltosIdleMonitorUI(this);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
static AltosWriter open_csv(File file) {
|
||||
try {
|
||||
return new AltosCSV(file);
|
||||
} catch (FileNotFoundException fe) {
|
||||
System.out.printf("%s\n", fe.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static AltosWriter open_kml(File file) {
|
||||
try {
|
||||
return new AltosKML(file);
|
||||
} catch (FileNotFoundException fe) {
|
||||
System.out.printf("%s\n", fe.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static AltosRecordSet record_set(File input) {
|
||||
try {
|
||||
return AltosLib.record_set(input);
|
||||
} catch (IOException ie) {
|
||||
String message = ie.getMessage();
|
||||
if (message == null)
|
||||
message = String.format("%s (I/O error)", input.toString());
|
||||
System.err.printf("%s: %s\n", input.toString(), message);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static final int process_none = 0;
|
||||
static final int process_csv = 1;
|
||||
static final int process_kml = 2;
|
||||
static final int process_graph = 3;
|
||||
static final int process_replay = 4;
|
||||
static final int process_summary = 5;
|
||||
static final int process_oneline = 6;
|
||||
|
||||
static boolean process_csv(File input) {
|
||||
AltosRecordSet set = record_set(input);
|
||||
if (set == null)
|
||||
return false;
|
||||
|
||||
File output = Altos.replace_extension(input,".csv");
|
||||
System.out.printf("Processing \"%s\" to \"%s\"\n", input, output);
|
||||
if (input.equals(output)) {
|
||||
System.out.printf("Not processing '%s'\n", input);
|
||||
return false;
|
||||
} else {
|
||||
AltosWriter writer = open_csv(output);
|
||||
if (writer == null)
|
||||
return false;
|
||||
AltosFlightSeries series = make_series(set);
|
||||
writer.write(series);
|
||||
writer.close();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean process_kml(File input) {
|
||||
AltosRecordSet set = record_set(input);
|
||||
if (set == null)
|
||||
return false;
|
||||
|
||||
File output = Altos.replace_extension(input,".kml");
|
||||
System.out.printf("Processing \"%s\" to \"%s\"\n", input, output);
|
||||
if (input.equals(output)) {
|
||||
System.out.printf("Not processing '%s'\n", input);
|
||||
return false;
|
||||
} else {
|
||||
AltosWriter writer = open_kml(output);
|
||||
if (writer == null)
|
||||
return false;
|
||||
AltosFlightSeries series = make_series(set);
|
||||
series.finish();
|
||||
writer.write(series);
|
||||
writer.close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static AltosReplayReader replay_file(File file) {
|
||||
AltosRecordSet set = record_set(file);
|
||||
if (set == null)
|
||||
return null;
|
||||
return new AltosReplayReader(set, file);
|
||||
}
|
||||
|
||||
static boolean process_replay(File file) {
|
||||
AltosReplayReader reader = replay_file(file);
|
||||
if (reader == null)
|
||||
return false;
|
||||
AltosFlightUI flight_ui = new AltosFlightUI(new AltosVoice(), reader);
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean process_graph(AltosUI altosui, File file) {
|
||||
AltosRecordSet set = record_set(file);
|
||||
return graph_file(altosui, set, file);
|
||||
}
|
||||
|
||||
static boolean process_summary(File file) {
|
||||
AltosRecordSet set = record_set(file);
|
||||
if (set == null)
|
||||
return false;
|
||||
System.out.printf("%s:\n", file.toString());
|
||||
AltosFlightSeries series = make_series(set);
|
||||
AltosFlightStats stats = new AltosFlightStats(series);
|
||||
if (stats.serial != AltosLib.MISSING)
|
||||
System.out.printf("Serial: %5d\n", stats.serial);
|
||||
if (stats.flight != AltosLib.MISSING)
|
||||
System.out.printf("Flight: %5d\n", stats.flight);
|
||||
if (stats.year != AltosLib.MISSING)
|
||||
System.out.printf("Date: %04d-%02d-%02d\n",
|
||||
stats.year, stats.month, stats.day);
|
||||
if (stats.hour != AltosLib.MISSING)
|
||||
System.out.printf("Time: %02d:%02d:%02d UTC\n",
|
||||
stats.hour, stats.minute, stats.second);
|
||||
if (stats.max_height != AltosLib.MISSING)
|
||||
System.out.printf("Max height: %6.0f m %6.0f ft\n",
|
||||
stats.max_height,
|
||||
AltosConvert.meters_to_feet(stats.max_height));
|
||||
if (stats.max_speed != AltosLib.MISSING)
|
||||
System.out.printf("Max speed: %6.0f m/s %6.0f ft/s %6.4f Mach\n",
|
||||
stats.max_speed,
|
||||
AltosConvert.meters_to_feet(stats.max_speed),
|
||||
AltosConvert.meters_to_mach(stats.max_speed));
|
||||
if (stats.max_acceleration != AltosLib.MISSING) {
|
||||
System.out.printf("Max accel: %6.0f m/s² %6.0f ft/s² %6.2f g\n",
|
||||
stats.max_acceleration,
|
||||
AltosConvert.meters_to_feet(stats.max_acceleration),
|
||||
AltosConvert.meters_to_g(stats.max_acceleration));
|
||||
}
|
||||
if (stats.state_speed[Altos.ao_flight_drogue] != AltosLib.MISSING)
|
||||
System.out.printf("Drogue rate: %6.0f m/s %6.0f ft/s\n",
|
||||
stats.state_speed[Altos.ao_flight_drogue],
|
||||
AltosConvert.meters_to_feet(stats.state_speed[Altos.ao_flight_drogue]));
|
||||
if (stats.state_speed[Altos.ao_flight_main] != AltosLib.MISSING)
|
||||
System.out.printf("Main rate: %6.0f m/s %6.0f ft/s\n",
|
||||
stats.state_speed[Altos.ao_flight_main],
|
||||
AltosConvert.meters_to_feet(stats.state_speed[Altos.ao_flight_main]));
|
||||
if (stats.landed_time != AltosLib.MISSING &&
|
||||
stats.boost_time != AltosLib.MISSING &&
|
||||
stats.landed_time > stats.boost_time)
|
||||
System.out.printf("Flight time: %6.0f s\n",
|
||||
stats.landed_time -
|
||||
stats.boost_time);
|
||||
System.out.printf("\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean process_oneline(File file) {
|
||||
AltosRecordSet set = record_set(file);
|
||||
if (set == null)
|
||||
return false;
|
||||
System.out.printf("%s", file.toString());
|
||||
AltosFlightSeries series = make_series(set);
|
||||
AltosFlightStats stats = new AltosFlightStats(series);
|
||||
if (stats.max_height != AltosLib.MISSING)
|
||||
System.out.printf(" height %6.0f m", stats.max_height);
|
||||
if (stats.max_speed != AltosLib.MISSING)
|
||||
System.out.printf(" speed %6.0f m/s", stats.max_speed);
|
||||
if (stats.state_enter_speed[AltosLib.ao_flight_drogue] != AltosLib.MISSING)
|
||||
System.out.printf(" drogue-deploy %6.0f m/s", stats.state_enter_speed[AltosLib.ao_flight_drogue]);
|
||||
if (stats.max_acceleration != AltosLib.MISSING)
|
||||
System.out.printf(" accel %6.0f m/s²", stats.max_acceleration);
|
||||
System.out.printf("\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void help(int code) {
|
||||
System.out.printf("Usage: altosui [OPTION]... [FILE]...\n");
|
||||
System.out.printf(" Options:\n");
|
||||
System.out.printf(" --replay <filename>\t\trelive the glory of past flights \n");
|
||||
System.out.printf(" --graph <filename>\t\tgraph a flight\n");
|
||||
System.out.printf(" --summary <filename>\t\tText summary of a flight\n");
|
||||
System.out.printf(" --oneline <filename>\t\tOne line summary of a flight\n");
|
||||
System.out.printf(" --csv\tgenerate comma separated output for spreadsheets, etc\n");
|
||||
System.out.printf(" --kml\tgenerate KML output for use with Google Earth\n");
|
||||
System.exit(code);
|
||||
}
|
||||
|
||||
public static void main(final String[] args) {
|
||||
int errors = 0;
|
||||
load_library(null);
|
||||
try {
|
||||
UIManager.setLookAndFeel(AltosUIPreferences.look_and_feel());
|
||||
} catch (Exception e) {
|
||||
}
|
||||
AltosUI altosui = null;
|
||||
|
||||
/* Handle batch-mode */
|
||||
if (args.length == 0) {
|
||||
altosui = new AltosUI();
|
||||
java.util.List<AltosDevice> devices = AltosUSBDevice.list(Altos.product_basestation);
|
||||
if (devices != null)
|
||||
for (AltosDevice device : devices)
|
||||
altosui.telemetry_window(device);
|
||||
} else {
|
||||
int process = process_none;
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (args[i].equals("--help"))
|
||||
help(0);
|
||||
else if (args[i].equals("--replay"))
|
||||
process = process_replay;
|
||||
else if (args[i].equals("--kml"))
|
||||
process = process_kml;
|
||||
else if (args[i].equals("--csv"))
|
||||
process = process_csv;
|
||||
else if (args[i].equals("--graph"))
|
||||
process = process_graph;
|
||||
else if (args[i].equals("--summary"))
|
||||
process = process_summary;
|
||||
else if (args[i].equals("--oneline"))
|
||||
process = process_oneline;
|
||||
else if (args[i].startsWith("--"))
|
||||
help(1);
|
||||
else {
|
||||
File file = new File(args[i]);
|
||||
switch (process) {
|
||||
case process_none:
|
||||
if (altosui == null)
|
||||
altosui = new AltosUI();
|
||||
case process_graph:
|
||||
if (!process_graph(null, file))
|
||||
++errors;
|
||||
break;
|
||||
case process_replay:
|
||||
if (!process_replay(file))
|
||||
++errors;
|
||||
break;
|
||||
case process_kml:
|
||||
if (!process_kml(file))
|
||||
++errors;
|
||||
break;
|
||||
case process_csv:
|
||||
if (!process_csv(file))
|
||||
++errors;
|
||||
break;
|
||||
case process_summary:
|
||||
if (!process_summary(file))
|
||||
++errors;
|
||||
break;
|
||||
case process_oneline:
|
||||
if (!process_oneline(file))
|
||||
++errors;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (errors != 0)
|
||||
System.exit(errors);
|
||||
}
|
||||
}
|
73
altosui/Info.plist.in
Normal file
73
altosui/Info.plist.in
Normal file
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
|
||||
<plist version="0.9">
|
||||
<dict>
|
||||
<key>CFBundleName</key>
|
||||
<string>AltosUI</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>@VERSION@</string>
|
||||
<key>CFBundleAllowMixedLocalizations</key>
|
||||
<string>true</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>JavaApplicationStub</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.altusmetrum.altosui</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>Altu</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>AltOS UI version @VERSION@</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>altusmetrum-altosui.icns</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>Telemetry</string>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>application-vnd.altusmetrum.telemetry.icns</string>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>telem</string>
|
||||
</array>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>Eeprom</string>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>application-vnd.altusmetrum.eeprom.icns</string>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>eeprom</string>
|
||||
</array>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>Java</key>
|
||||
<dict>
|
||||
<key>MainClass</key>
|
||||
<string>altosui.AltosUI</string>
|
||||
<key>JVMVersion</key>
|
||||
<string>1.5+</string>
|
||||
<key>ClassPath</key>
|
||||
<array>
|
||||
<string>$JAVAROOT/altosui.jar</string>
|
||||
<string>$JAVAROOT/freetts.jar</string>
|
||||
</array>
|
||||
<key>VMOptions</key>
|
||||
<array>
|
||||
<string>-Xms512M</string>
|
||||
<string>-Xmx512M</string>
|
||||
<string>-Dosgi.clean=true</string>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
84
altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi
Normal file
84
altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi
Normal file
@@ -0,0 +1,84 @@
|
||||
#
|
||||
# InstDrv Example, (c) 2003 Jan Kiszka (Jan Kiszka@web.de)
|
||||
#
|
||||
|
||||
Name "InstDrv.dll test"
|
||||
|
||||
OutFile "InstDrv-Test.exe"
|
||||
|
||||
ShowInstDetails show
|
||||
|
||||
ComponentText "InstDrv Plugin Usage Example"
|
||||
|
||||
Page components
|
||||
Page instfiles
|
||||
|
||||
Section "Install a Driver" InstDriver
|
||||
InstDrv::InitDriverSetup /NOUNLOAD "{4d36e978-e325-11ce-bfc1-08002be10318}" "IrCOMM2k"
|
||||
Pop $0
|
||||
DetailPrint "InitDriverSetup: $0"
|
||||
|
||||
InstDrv::DeleteOemInfFiles /NOUNLOAD
|
||||
Pop $0
|
||||
DetailPrint "DeleteOemInfFiles: $0"
|
||||
StrCmp $0 "00000000" PrintInfNames ContInst1
|
||||
|
||||
PrintInfNames:
|
||||
Pop $0
|
||||
DetailPrint "Deleted $0"
|
||||
Pop $0
|
||||
DetailPrint "Deleted $0"
|
||||
|
||||
ContInst1:
|
||||
InstDrv::CreateDevice /NOUNLOAD
|
||||
Pop $0
|
||||
DetailPrint "CreateDevice: $0"
|
||||
|
||||
SetOutPath $TEMP
|
||||
File "ircomm2k.inf"
|
||||
File "ircomm2k.sys"
|
||||
|
||||
InstDrv::InstallDriver /NOUNLOAD "$TEMP\ircomm2k.inf"
|
||||
Pop $0
|
||||
DetailPrint "InstallDriver: $0"
|
||||
StrCmp $0 "00000000" PrintReboot ContInst2
|
||||
|
||||
PrintReboot:
|
||||
Pop $0
|
||||
DetailPrint "Reboot: $0"
|
||||
|
||||
ContInst2:
|
||||
InstDrv::CountDevices
|
||||
Pop $0
|
||||
DetailPrint "CountDevices: $0"
|
||||
SectionEnd
|
||||
|
||||
Section "Uninstall the driver again" UninstDriver
|
||||
InstDrv::InitDriverSetup /NOUNLOAD "{4d36e978-e325-11ce-bfc1-08002be10318}" "IrCOMM2k"
|
||||
Pop $0
|
||||
DetailPrint "InitDriverSetup: $0"
|
||||
|
||||
InstDrv::DeleteOemInfFiles /NOUNLOAD
|
||||
Pop $0
|
||||
DetailPrint "DeleteOemInfFiles: $0"
|
||||
StrCmp $0 "00000000" PrintInfNames ContUninst1
|
||||
|
||||
PrintInfNames:
|
||||
Pop $0
|
||||
DetailPrint "Deleted $0"
|
||||
Pop $0
|
||||
DetailPrint "Deleted $0"
|
||||
|
||||
ContUninst1:
|
||||
InstDrv::RemoveAllDevices
|
||||
Pop $0
|
||||
DetailPrint "RemoveAllDevices: $0"
|
||||
StrCmp $0 "00000000" PrintReboot ContUninst2
|
||||
|
||||
PrintReboot:
|
||||
Pop $0
|
||||
DetailPrint "Reboot: $0"
|
||||
|
||||
ContUninst2:
|
||||
Delete "$SYSDIR\system32\ircomm2k.sys"
|
||||
SectionEnd
|
BIN
altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe
Normal file
BIN
altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe
Normal file
Binary file not shown.
704
altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c
Normal file
704
altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c
Normal file
@@ -0,0 +1,704 @@
|
||||
/*
|
||||
|
||||
InstDrv.dll - Installs or Removes Device Drivers
|
||||
|
||||
Copyright <20> 2003 Jan Kiszka (Jan.Kiszka@web.de)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute
|
||||
it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented;
|
||||
you must not claim that you wrote the original software.
|
||||
If you use this software in a product, an acknowledgment in the
|
||||
product documentation would be appreciated but is not required.
|
||||
2. Altered versions must be plainly marked as such,
|
||||
and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any distribution.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
#include <setupapi.h>
|
||||
#include <newdev.h>
|
||||
#include "../exdll/exdll.h"
|
||||
|
||||
|
||||
char paramBuf[1024];
|
||||
GUID devClass;
|
||||
char hwIdBuf[1024];
|
||||
int initialized = 0;
|
||||
|
||||
|
||||
|
||||
void* memset(void* dst, int val, unsigned int len)
|
||||
{
|
||||
while (len-- > 0)
|
||||
*((char *)dst)++ = val;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void* memcpy(void* dst, const void* src, unsigned int len)
|
||||
{
|
||||
while (len-- > 0)
|
||||
*((char *)dst)++ = *((char *)src)++;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int HexCharToInt(char c)
|
||||
{
|
||||
if ((c >= '0') && (c <= '9'))
|
||||
return c - '0';
|
||||
else if ((c >= 'a') && (c <= 'f'))
|
||||
return c - 'a' + 10;
|
||||
else if ((c >= 'A') && (c <= 'F'))
|
||||
return c - 'A' + 10;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOLEAN HexStringToUInt(char* str, int width, void* valBuf)
|
||||
{
|
||||
int i, val;
|
||||
|
||||
|
||||
for (i = width - 4; i >= 0; i -= 4)
|
||||
{
|
||||
val = HexCharToInt(*str++);
|
||||
if (val < 0)
|
||||
return FALSE;
|
||||
*(unsigned int *)valBuf += val << i;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOLEAN StringToGUID(char* guidStr, GUID* pGuid)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
memset(pGuid, 0, sizeof(GUID));
|
||||
|
||||
if (*guidStr++ != '{')
|
||||
return FALSE;
|
||||
|
||||
if (!HexStringToUInt(guidStr, 32, &pGuid->Data1))
|
||||
return FALSE;
|
||||
guidStr += 8;
|
||||
|
||||
if (*guidStr++ != '-')
|
||||
return FALSE;
|
||||
|
||||
if (!HexStringToUInt(guidStr, 16, &pGuid->Data2))
|
||||
return FALSE;
|
||||
guidStr += 4;
|
||||
|
||||
if (*guidStr++ != '-')
|
||||
return FALSE;
|
||||
|
||||
if (!HexStringToUInt(guidStr, 16, &pGuid->Data3))
|
||||
return FALSE;
|
||||
guidStr += 4;
|
||||
|
||||
if (*guidStr++ != '-')
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
if (!HexStringToUInt(guidStr, 8, &pGuid->Data4[i]))
|
||||
return FALSE;
|
||||
guidStr += 2;
|
||||
}
|
||||
|
||||
if (*guidStr++ != '-')
|
||||
return FALSE;
|
||||
|
||||
for (i = 2; i < 8; i++)
|
||||
{
|
||||
if (!HexStringToUInt(guidStr, 8, &pGuid->Data4[i]))
|
||||
return FALSE;
|
||||
guidStr += 2;
|
||||
}
|
||||
|
||||
if (*guidStr++ != '}')
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DWORD FindNextDevice(HDEVINFO devInfoSet, SP_DEVINFO_DATA* pDevInfoData, DWORD* pIndex)
|
||||
{
|
||||
DWORD buffersize = 0;
|
||||
LPTSTR buffer = NULL;
|
||||
DWORD dataType;
|
||||
DWORD result;
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (!SetupDiEnumDeviceInfo(devInfoSet, (*pIndex)++, pDevInfoData))
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
GetDeviceRegistryProperty:
|
||||
if (!SetupDiGetDeviceRegistryProperty(devInfoSet, pDevInfoData, SPDRP_HARDWAREID,
|
||||
&dataType, (PBYTE)buffer, buffersize,
|
||||
&buffersize))
|
||||
{
|
||||
result = GetLastError();
|
||||
|
||||
if (result == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
if (buffer != NULL)
|
||||
LocalFree(buffer);
|
||||
|
||||
buffer = (LPTSTR)LocalAlloc(LPTR, buffersize);
|
||||
|
||||
if (buffer == NULL)
|
||||
break;
|
||||
|
||||
goto GetDeviceRegistryProperty;
|
||||
}
|
||||
else if (result == ERROR_INVALID_DATA)
|
||||
continue; // ignore invalid entries
|
||||
else
|
||||
break; // break on other errors
|
||||
}
|
||||
|
||||
if (lstrcmpi(buffer, hwIdBuf) == 0)
|
||||
{
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer != NULL)
|
||||
LocalFree(buffer);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DWORD FindFirstDevice(HWND hwndParent, const GUID* pDevClass, const LPTSTR hwId,
|
||||
HDEVINFO* pDevInfoSet, SP_DEVINFO_DATA* pDevInfoData,
|
||||
DWORD *pIndex, DWORD flags)
|
||||
{
|
||||
DWORD result;
|
||||
|
||||
|
||||
*pDevInfoSet = SetupDiGetClassDevs((GUID*)pDevClass, NULL, hwndParent, flags);
|
||||
if (*pDevInfoSet == INVALID_HANDLE_VALUE)
|
||||
return GetLastError();
|
||||
|
||||
pDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
*pIndex = 0;
|
||||
|
||||
result = FindNextDevice(*pDevInfoSet, pDevInfoData, pIndex);
|
||||
|
||||
if (result != 0)
|
||||
SetupDiDestroyDeviceInfoList(*pDevInfoSet);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* InstDrv::InitDriverSetup devClass drvHWID
|
||||
*
|
||||
* devClass - GUID of the driver's device setup class
|
||||
* drvHWID - Hardware ID of the supported device
|
||||
*
|
||||
* Return:
|
||||
* result - error message, empty on success
|
||||
*/
|
||||
void __declspec(dllexport) InitDriverSetup(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
|
||||
{
|
||||
EXDLL_INIT();
|
||||
|
||||
/* convert class GUID */
|
||||
popstring(paramBuf);
|
||||
|
||||
if (!StringToGUID(paramBuf, &devClass))
|
||||
{
|
||||
popstring(paramBuf);
|
||||
pushstring("Invalid GUID!");
|
||||
return;
|
||||
}
|
||||
|
||||
/* get hardware ID */
|
||||
memset(hwIdBuf, 0, sizeof(hwIdBuf));
|
||||
popstring(hwIdBuf);
|
||||
|
||||
initialized = 1;
|
||||
pushstring("");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* InstDrv::CountDevices
|
||||
*
|
||||
* Return:
|
||||
* result - Number of installed devices the driver supports
|
||||
*/
|
||||
void __declspec(dllexport) CountDevices(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
|
||||
{
|
||||
HDEVINFO devInfoSet;
|
||||
SP_DEVINFO_DATA devInfoData;
|
||||
int count = 0;
|
||||
char countBuf[16];
|
||||
DWORD index;
|
||||
DWORD result;
|
||||
|
||||
|
||||
EXDLL_INIT();
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
pushstring("Fatal error!");
|
||||
return;
|
||||
}
|
||||
|
||||
result = FindFirstDevice(hwndParent, &devClass, hwIdBuf, &devInfoSet, &devInfoData,
|
||||
&index, DIGCF_PRESENT);
|
||||
if (result != 0)
|
||||
{
|
||||
pushstring("0");
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
count++;
|
||||
} while (FindNextDevice(devInfoSet, &devInfoData, &index) == 0);
|
||||
|
||||
SetupDiDestroyDeviceInfoList(devInfoSet);
|
||||
|
||||
wsprintf(countBuf, "%d", count);
|
||||
pushstring(countBuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* InstDrv::CreateDevice
|
||||
*
|
||||
* Return:
|
||||
* result - Windows error code
|
||||
*/
|
||||
void __declspec(dllexport) CreateDevice(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
|
||||
{
|
||||
HDEVINFO devInfoSet;
|
||||
SP_DEVINFO_DATA devInfoData;
|
||||
DWORD result = 0;
|
||||
char resultBuf[16];
|
||||
|
||||
|
||||
EXDLL_INIT();
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
pushstring("Fatal error!");
|
||||
return;
|
||||
}
|
||||
|
||||
devInfoSet = SetupDiCreateDeviceInfoList(&devClass, hwndParent);
|
||||
if (devInfoSet == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
wsprintf(resultBuf, "%08X", GetLastError());
|
||||
pushstring(resultBuf);
|
||||
return;
|
||||
}
|
||||
|
||||
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
if (!SetupDiCreateDeviceInfo(devInfoSet, hwIdBuf, &devClass, NULL,
|
||||
hwndParent, DICD_GENERATE_ID, &devInfoData))
|
||||
{
|
||||
result = GetLastError();
|
||||
goto InstallCleanup;
|
||||
}
|
||||
|
||||
if (!SetupDiSetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_HARDWAREID,
|
||||
hwIdBuf, (lstrlen(hwIdBuf)+2)*sizeof(TCHAR)))
|
||||
{
|
||||
result = GetLastError();
|
||||
goto InstallCleanup;
|
||||
}
|
||||
|
||||
if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, devInfoSet, &devInfoData))
|
||||
result = GetLastError();
|
||||
|
||||
InstallCleanup:
|
||||
SetupDiDestroyDeviceInfoList(devInfoSet);
|
||||
|
||||
wsprintf(resultBuf, "%08X", result);
|
||||
pushstring(resultBuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* InstDrv::InstallDriver infPath
|
||||
*
|
||||
* Return:
|
||||
* result - Windows error code
|
||||
* reboot - non-zero if reboot is required
|
||||
*/
|
||||
void __declspec(dllexport) InstallDriver(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
|
||||
{
|
||||
char resultBuf[16];
|
||||
BOOL reboot;
|
||||
|
||||
|
||||
EXDLL_INIT();
|
||||
popstring(paramBuf);
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
pushstring("Fatal error!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!UpdateDriverForPlugAndPlayDevices(hwndParent, hwIdBuf, paramBuf,
|
||||
INSTALLFLAG_FORCE, &reboot))
|
||||
{
|
||||
wsprintf(resultBuf, "%08X", GetLastError());
|
||||
pushstring(resultBuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
wsprintf(resultBuf, "%d", reboot);
|
||||
pushstring(resultBuf);
|
||||
pushstring("00000000");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* InstDrv::DeleteOemInfFiles
|
||||
*
|
||||
* Return:
|
||||
* result - Windows error code
|
||||
* oeminf - Path of the deleted devices setup file (oemXX.inf)
|
||||
* oempnf - Path of the deleted devices setup file (oemXX.pnf)
|
||||
*/
|
||||
void __declspec(dllexport) DeleteOemInfFiles(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
|
||||
{
|
||||
HDEVINFO devInfo;
|
||||
SP_DEVINFO_DATA devInfoData;
|
||||
SP_DRVINFO_DATA drvInfoData;
|
||||
SP_DRVINFO_DETAIL_DATA drvInfoDetail;
|
||||
DWORD index;
|
||||
DWORD result;
|
||||
char resultBuf[16];
|
||||
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
pushstring("Fatal error!");
|
||||
return;
|
||||
}
|
||||
|
||||
result = FindFirstDevice(NULL, &devClass, hwIdBuf, &devInfo, &devInfoData, &index, 0);
|
||||
if (result != 0)
|
||||
goto Cleanup1;
|
||||
|
||||
if (!SetupDiBuildDriverInfoList(devInfo, &devInfoData, SPDIT_COMPATDRIVER))
|
||||
{
|
||||
result = GetLastError();
|
||||
goto Cleanup2;
|
||||
}
|
||||
|
||||
drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
|
||||
drvInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
|
||||
|
||||
if (!SetupDiEnumDriverInfo(devInfo, &devInfoData, SPDIT_COMPATDRIVER, 0, &drvInfoData))
|
||||
{
|
||||
result = GetLastError();
|
||||
goto Cleanup3;
|
||||
}
|
||||
|
||||
if (!SetupDiGetDriverInfoDetail(devInfo, &devInfoData, &drvInfoData,
|
||||
&drvInfoDetail, sizeof(drvInfoDetail), NULL))
|
||||
{
|
||||
result = GetLastError();
|
||||
|
||||
if (result != ERROR_INSUFFICIENT_BUFFER)
|
||||
goto Cleanup3;
|
||||
|
||||
result = 0;
|
||||
}
|
||||
|
||||
pushstring(drvInfoDetail.InfFileName);
|
||||
if (!DeleteFile(drvInfoDetail.InfFileName))
|
||||
result = GetLastError();
|
||||
else
|
||||
{
|
||||
index = lstrlen(drvInfoDetail.InfFileName);
|
||||
if (index > 3)
|
||||
{
|
||||
lstrcpy(drvInfoDetail.InfFileName+index-3, "pnf");
|
||||
pushstring(drvInfoDetail.InfFileName);
|
||||
if (!DeleteFile(drvInfoDetail.InfFileName))
|
||||
result = GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
Cleanup3:
|
||||
SetupDiDestroyDriverInfoList(devInfo, &devInfoData, SPDIT_COMPATDRIVER);
|
||||
|
||||
Cleanup2:
|
||||
SetupDiDestroyDeviceInfoList(devInfo);
|
||||
|
||||
Cleanup1:
|
||||
wsprintf(resultBuf, "%08X", result);
|
||||
pushstring(resultBuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* InstDrv::RemoveAllDevices
|
||||
*
|
||||
* Return:
|
||||
* result - Windows error code
|
||||
* reboot - non-zero if reboot is required
|
||||
*/
|
||||
void __declspec(dllexport) RemoveAllDevices(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
|
||||
{
|
||||
HDEVINFO devInfo;
|
||||
SP_DEVINFO_DATA devInfoData;
|
||||
DWORD index;
|
||||
DWORD result;
|
||||
char resultBuf[16];
|
||||
BOOL reboot = FALSE;
|
||||
SP_DEVINSTALL_PARAMS instParams;
|
||||
|
||||
|
||||
EXDLL_INIT();
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
pushstring("Fatal error!");
|
||||
return;
|
||||
}
|
||||
|
||||
result = FindFirstDevice(NULL, &devClass, hwIdBuf, &devInfo, &devInfoData, &index, 0);
|
||||
if (result != 0)
|
||||
goto Cleanup1;
|
||||
|
||||
do
|
||||
{
|
||||
if (!SetupDiCallClassInstaller(DIF_REMOVE, devInfo, &devInfoData))
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
instParams.cbSize = sizeof(instParams);
|
||||
if (!reboot &&
|
||||
SetupDiGetDeviceInstallParams(devInfo, &devInfoData, &instParams) &&
|
||||
((instParams.Flags & (DI_NEEDRESTART|DI_NEEDREBOOT)) != 0))
|
||||
{
|
||||
reboot = TRUE;
|
||||
}
|
||||
|
||||
result = FindNextDevice(devInfo, &devInfoData, &index);
|
||||
} while (result == 0);
|
||||
|
||||
SetupDiDestroyDeviceInfoList(devInfo);
|
||||
|
||||
Cleanup1:
|
||||
if ((result == 0) || (result == ERROR_NO_MORE_ITEMS))
|
||||
{
|
||||
wsprintf(resultBuf, "%d", reboot);
|
||||
pushstring(resultBuf);
|
||||
pushstring("00000000");
|
||||
}
|
||||
else
|
||||
{
|
||||
wsprintf(resultBuf, "%08X", result);
|
||||
pushstring(resultBuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* InstDrv::StartSystemService serviceName
|
||||
*
|
||||
* Return:
|
||||
* result - Windows error code
|
||||
*/
|
||||
void __declspec(dllexport) StartSystemService(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
|
||||
{
|
||||
SC_HANDLE managerHndl;
|
||||
SC_HANDLE svcHndl;
|
||||
SERVICE_STATUS svcStatus;
|
||||
DWORD oldCheckPoint;
|
||||
DWORD result;
|
||||
char resultBuf[16];
|
||||
|
||||
|
||||
EXDLL_INIT();
|
||||
popstring(paramBuf);
|
||||
|
||||
managerHndl = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
||||
if (managerHndl == NULL)
|
||||
{
|
||||
result = GetLastError();
|
||||
goto Cleanup1;
|
||||
}
|
||||
|
||||
svcHndl = OpenService(managerHndl, paramBuf, SERVICE_START | SERVICE_QUERY_STATUS);
|
||||
if (svcHndl == NULL)
|
||||
{
|
||||
result = GetLastError();
|
||||
goto Cleanup2;
|
||||
}
|
||||
|
||||
if (!StartService(svcHndl, 0, NULL) || !QueryServiceStatus(svcHndl, &svcStatus))
|
||||
{
|
||||
result = GetLastError();
|
||||
goto Cleanup3;
|
||||
}
|
||||
|
||||
while (svcStatus.dwCurrentState == SERVICE_START_PENDING)
|
||||
{
|
||||
oldCheckPoint = svcStatus.dwCheckPoint;
|
||||
|
||||
Sleep(svcStatus.dwWaitHint);
|
||||
|
||||
if (!QueryServiceStatus(svcHndl, &svcStatus))
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
if (oldCheckPoint >= svcStatus.dwCheckPoint)
|
||||
{
|
||||
if ((svcStatus.dwCurrentState == SERVICE_STOPPED) &&
|
||||
(svcStatus.dwWin32ExitCode != 0))
|
||||
result = svcStatus.dwWin32ExitCode;
|
||||
else
|
||||
result = ERROR_SERVICE_REQUEST_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
if (svcStatus.dwCurrentState == SERVICE_RUNNING)
|
||||
result = 0;
|
||||
|
||||
Cleanup3:
|
||||
CloseServiceHandle(svcHndl);
|
||||
|
||||
Cleanup2:
|
||||
CloseServiceHandle(managerHndl);
|
||||
|
||||
Cleanup1:
|
||||
wsprintf(resultBuf, "%08X", result);
|
||||
pushstring(resultBuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* InstDrv::StopSystemService serviceName
|
||||
*
|
||||
* Return:
|
||||
* result - Windows error code
|
||||
*/
|
||||
void __declspec(dllexport) StopSystemService(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
|
||||
{
|
||||
SC_HANDLE managerHndl;
|
||||
SC_HANDLE svcHndl;
|
||||
SERVICE_STATUS svcStatus;
|
||||
DWORD oldCheckPoint;
|
||||
DWORD result;
|
||||
char resultBuf[16];
|
||||
|
||||
|
||||
EXDLL_INIT();
|
||||
popstring(paramBuf);
|
||||
|
||||
managerHndl = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
||||
if (managerHndl == NULL)
|
||||
{
|
||||
result = GetLastError();
|
||||
goto Cleanup1;
|
||||
}
|
||||
|
||||
svcHndl = OpenService(managerHndl, paramBuf, SERVICE_STOP | SERVICE_QUERY_STATUS);
|
||||
if (svcHndl == NULL)
|
||||
{
|
||||
result = GetLastError();
|
||||
goto Cleanup2;
|
||||
}
|
||||
|
||||
if (!ControlService(svcHndl, SERVICE_CONTROL_STOP, &svcStatus))
|
||||
{
|
||||
result = GetLastError();
|
||||
goto Cleanup3;
|
||||
}
|
||||
|
||||
while (svcStatus.dwCurrentState == SERVICE_STOP_PENDING)
|
||||
{
|
||||
oldCheckPoint = svcStatus.dwCheckPoint;
|
||||
|
||||
Sleep(svcStatus.dwWaitHint);
|
||||
|
||||
if (!QueryServiceStatus(svcHndl, &svcStatus))
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
if (oldCheckPoint >= svcStatus.dwCheckPoint)
|
||||
{
|
||||
result = ERROR_SERVICE_REQUEST_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (svcStatus.dwCurrentState == SERVICE_STOPPED)
|
||||
result = 0;
|
||||
|
||||
Cleanup3:
|
||||
CloseServiceHandle(svcHndl);
|
||||
|
||||
Cleanup2:
|
||||
CloseServiceHandle(managerHndl);
|
||||
|
||||
Cleanup1:
|
||||
wsprintf(resultBuf, "%08X", result);
|
||||
pushstring(resultBuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
110
altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp
Normal file
110
altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp
Normal file
@@ -0,0 +1,110 @@
|
||||
# Microsoft Developer Studio Project File - Name="InstDrv" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** NICHT BEARBEITEN **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=InstDrv - Win32 Debug
|
||||
!MESSAGE Dies ist kein g<>ltiges Makefile. Zum Erstellen dieses Projekts mit NMAKE
|
||||
!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und f<>hren Sie den Befehl
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "InstDrv.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE Sie k<>nnen beim Ausf<73>hren von NMAKE eine Konfiguration angeben
|
||||
!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "InstDrv.mak" CFG="InstDrv - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE F<>r die Konfiguration stehen zur Auswahl:
|
||||
!MESSAGE
|
||||
!MESSAGE "InstDrv - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "InstDrv - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "InstDrv - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 1
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTDRV_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /MT /W3 /GX /O1 /I "C:\Programme\WINDDK\3790\inc\ddk\w2k" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTDRV_EXPORTS" /FD /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x407 /d "NDEBUG"
|
||||
# ADD RSC /l 0x407 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib setupapi.lib newdev.lib /nologo /entry:"_DllMainCRTStartup" /dll /machine:I386 /nodefaultlib /out:"../../Plugins/InstDrv.dll" /libpath:"C:\Programme\WINDDK\3790\lib\w2k\i386" /opt:nowin98
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "InstDrv - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTDRV_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTDRV_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x407 /d "_DEBUG"
|
||||
# ADD RSC /l 0x407 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"_DllMainCRTStartup" /dll /debug /machine:I386 /pdbtype:sept
|
||||
# SUBTRACT LINK32 /nodefaultlib
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "InstDrv - Win32 Release"
|
||||
# Name "InstDrv - Win32 Debug"
|
||||
# Begin Group "Quellcodedateien"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\InstDrv.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header-Dateien"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# End Group
|
||||
# Begin Group "Ressourcendateien"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
29
altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw
Normal file
29
altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw
Normal file
@@ -0,0 +1,29 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GEL<45>SCHT WERDEN!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "InstDrv"=.\InstDrv.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
141
altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt
Normal file
141
altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt
Normal file
@@ -0,0 +1,141 @@
|
||||
InstDrv.dll version 0.2 - Installs or Removes Device Drivers
|
||||
------------------------------------------------------------
|
||||
|
||||
|
||||
The plugin helps you to create NSIS scripts for installing device drivers or
|
||||
removing them again. It can count installed device instances, create new ones
|
||||
or delete all supported device. InstDrv works on Windows 2000 or later.
|
||||
|
||||
|
||||
|
||||
InstDrv::InitDriverSetup devClass drvHWID
|
||||
Return: result
|
||||
|
||||
To start processing a driver, first call this function. devClass is the GUID
|
||||
of the device class the driver supports, drvHWID is the device hardware ID. If
|
||||
you don't know what these terms mean, you may want to take a look at the
|
||||
Windows DDK. This function returns an empty string on success, otherwise an
|
||||
error message.
|
||||
|
||||
InitDriverSetup has to be called every time after the plugin dll has been
|
||||
(re-)loaded, or if you want to switch to a different driver.
|
||||
|
||||
|
||||
|
||||
InstDrv::CountDevices
|
||||
Return: number
|
||||
|
||||
This call returns the number of installed and supported devices of the driver.
|
||||
|
||||
|
||||
|
||||
InstDrv::CreateDevice
|
||||
Return: result
|
||||
|
||||
To create a new deviced node which the driver has to support, use this
|
||||
function. You may even call it multiple times for more than one instance. The
|
||||
return value is the Windows error code (in hex). Use CreateDevice before
|
||||
installing or updating the driver itself.
|
||||
|
||||
|
||||
|
||||
InstDrv::InstallDriver infPath
|
||||
Return: result
|
||||
reboot
|
||||
|
||||
InstallDriver installs or updates a device driver as specified in the .inf
|
||||
setup script. It returns a Windows error code (in hex) and, on success, a flag
|
||||
signalling if a system reboot is required.
|
||||
|
||||
|
||||
|
||||
InstDrv::DeleteOemInfFiles
|
||||
Return: result
|
||||
oeminf
|
||||
oempnf
|
||||
|
||||
DeleteOemInfFiles tries to clean up the Windows inf directory by deleting the
|
||||
oemXX.inf and oemXX.pnf files associated with the drivers. It returns a
|
||||
Windows error code (in hex) and, on success, the names of the deleted files.
|
||||
This functions requires that at least one device instance is still present.
|
||||
So, call it before you remove the devices itself. You should also call it
|
||||
before updating a driver. This avoids that the inf directory gets slowly
|
||||
messed up with useless old setup scripts (which does NOT really accelerate
|
||||
Windows). The error code which comes up when no device is installed is
|
||||
"00000103".
|
||||
|
||||
|
||||
|
||||
InstDrv::RemoveAllDevices
|
||||
Return: result
|
||||
reboot
|
||||
|
||||
This functions deletes all devices instances the driver supported. It returns
|
||||
a Windows error code (in hex) and, on success, a flag signalling if the system
|
||||
needs to be rebooted. You additionally have to remove the driver binaries from
|
||||
the system paths.
|
||||
|
||||
|
||||
|
||||
InstDrv::StartSystemService serviceName
|
||||
Return: result
|
||||
|
||||
Call this function to start the provided system service. The function blocks
|
||||
until the service is started or the system reported a timeout. The return value
|
||||
is the Windows error code (in hex).
|
||||
|
||||
|
||||
|
||||
InstDrv::StopSystemService serviceName
|
||||
Return: result
|
||||
|
||||
This function tries to stop the provided system service. It blocks until the
|
||||
service has been shut down or the system reported a timeout. The return value
|
||||
is the Windows error code (in hex).
|
||||
|
||||
|
||||
|
||||
Example.nsi
|
||||
|
||||
The example script installs or removes the virtual COM port driver of IrCOMM2k
|
||||
(2.0.0-alpha8, see www.ircomm2k.de/english). The driver and its setup script
|
||||
are only included for demonstration purposes, they do not work without the
|
||||
rest of IrCOMM2k (but they also do not cause any harm).
|
||||
|
||||
|
||||
|
||||
Building the Source Code
|
||||
|
||||
To build the plugin from the source code, some include files and libraries
|
||||
which come with the Windows DDK are required.
|
||||
|
||||
|
||||
|
||||
History
|
||||
|
||||
0.2 - fixed bug when calling InitDriverSetup the second time
|
||||
- added StartSystemService and StopSystemService
|
||||
|
||||
0.1 - first release
|
||||
|
||||
|
||||
|
||||
License
|
||||
|
||||
Copyright <20> 2003 Jan Kiszka (Jan.Kiszka@web.de)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute
|
||||
it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented;
|
||||
you must not claim that you wrote the original software.
|
||||
If you use this software in a product, an acknowledgment in the
|
||||
product documentation would be appreciated but is not required.
|
||||
2. Altered versions must be plainly marked as such,
|
||||
and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any distribution.
|
137
altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf
Normal file
137
altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf
Normal file
@@ -0,0 +1,137 @@
|
||||
; IrCOMM2k.inf
|
||||
;
|
||||
; Installation file for the Virtual Infrared-COM-Port
|
||||
;
|
||||
; (c) Copyright 2001, 2002 Jan Kiszka
|
||||
;
|
||||
|
||||
[Version]
|
||||
Signature="$Windows NT$"
|
||||
Provider=%JK%
|
||||
Class=Ports
|
||||
ClassGUID={4d36e978-e325-11ce-bfc1-08002be10318}
|
||||
;DriverVer=03/26/2002,1.2.1.0
|
||||
|
||||
[DestinationDirs]
|
||||
IrCOMM2k.Copy2Drivers = 12
|
||||
IrCOMM2k.Copy2Winnt = 10
|
||||
IrCOMM2k.Copy2System32 = 11
|
||||
IrCOMM2k.Copy2Help = 18
|
||||
|
||||
|
||||
;
|
||||
; Driver information
|
||||
;
|
||||
|
||||
[Manufacturer]
|
||||
%JK% = JK.Mfg
|
||||
|
||||
[JK.Mfg]
|
||||
%JK.DeviceDescIrCOMM% = IrCOMM2k_inst,IrCOMM2k
|
||||
|
||||
|
||||
;
|
||||
; General installation section
|
||||
;
|
||||
|
||||
[IrCOMM2k_inst]
|
||||
CopyFiles = IrCOMM2k.Copy2Drivers ;,IrCOMM2k.Copy2System32,IrCOMM2k.Copy2Help,IrCOMM2k.Copy2Winnt
|
||||
;AddReg = IrCOMM2k_inst_AddReg
|
||||
|
||||
|
||||
;
|
||||
; File sections
|
||||
;
|
||||
|
||||
[IrCOMM2k.Copy2Drivers]
|
||||
ircomm2k.sys,,,2
|
||||
|
||||
;[IrCOMM2k.Copy2System32]
|
||||
;ircomm2k.exe,,,2
|
||||
;ircomm2k.dll,,,2
|
||||
|
||||
;[IrCOMM2k.Copy2Help]
|
||||
;ircomm2k.hlp,,,2
|
||||
|
||||
;[IrCOMM2k.Copy2Winnt]
|
||||
;IrCOMM2k-Setup.exe,Setup.exe,,2
|
||||
|
||||
|
||||
;
|
||||
; Service Installation
|
||||
;
|
||||
|
||||
[IrCOMM2k_inst.Services]
|
||||
AddService = IrCOMM2k,0x00000002,IrCOMM2k_DriverService_Inst,IrCOMM2k_DriverEventLog_Inst
|
||||
;AddService = IrCOMM2kSvc,,IrCOMM2k_Service_Inst
|
||||
|
||||
[IrCOMM2k_DriverService_Inst]
|
||||
DisplayName = %IrCOMM2k.DrvName%
|
||||
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
|
||||
StartType = 3 ; SERVICE_DEMAND_START
|
||||
ErrorControl = 0 ; SERVICE_ERROR_IGNORE
|
||||
ServiceBinary = %12%\ircomm2k.sys
|
||||
|
||||
;[IrCOMM2k_Service_Inst]
|
||||
;DisplayName = %IrCOMM2k.SvcName%
|
||||
;Description = %IrCOMM2k.SvcDesc%
|
||||
;ServiceType = 0x00000120 ; SERVICE_WIN32_SHARE_PROCESS, SERVICE_INTERACTIVE_PROCESS
|
||||
;StartType = 2 ; SERVICE_AUTO_START
|
||||
;ErrorControl = 0 ; SERVICE_ERROR_IGNORE
|
||||
;ServiceBinary = %11%\ircomm2k.exe
|
||||
;Dependencies = IrCOMM2k
|
||||
;AddReg = IrCOMM2kSvcAddReg
|
||||
|
||||
|
||||
[IrCOMM2k_inst.nt.HW]
|
||||
AddReg=IrCOMM2kHwAddReg
|
||||
|
||||
[IrCOMM2kHwAddReg]
|
||||
HKR,,PortSubClass,REG_BINARY,0x00000001
|
||||
;HKR,,TimeoutScaling,REG_DWORD,0x00000001
|
||||
;HKR,,StatusLines,REG_DWORD,0x00000000
|
||||
|
||||
;[IrCOMM2k_inst_AddReg]
|
||||
;HKR,,EnumPropPages32,,"ircomm2k.dll,IrCOMM2kPropPageProvider"
|
||||
;HKLM,%UNINSTALL_KEY%,DisplayIcon,0x00020000,"%windir%\IrCOMM2k-Setup.exe"
|
||||
;HKLM,%UNINSTALL_KEY%,DisplayName,,"IrCOMM2k 1.2.1 "
|
||||
;HKLM,%UNINSTALL_KEY%,DisplayVersion,,"1.2.1"
|
||||
;HKLM,%UNINSTALL_KEY%,HelpLink,,"http://www.ircomm2k.de"
|
||||
;HKLM,%UNINSTALL_KEY%,Publisher,,%JK%
|
||||
;HKLM,%UNINSTALL_KEY%,UninstallString,0x00020000,"%windir%\IrCOMM2k-Setup.exe"
|
||||
|
||||
;[IrCOMM2kSvcAddReg]
|
||||
;HKR,Parameters,ActiveConnectOnly,REG_DWORD,0x00000000
|
||||
|
||||
|
||||
[IrCOMM2k_DriverEventLog_Inst]
|
||||
AddReg = IrCOMM2k_DriverEventLog_AddReg
|
||||
|
||||
[IrCOMM2k_DriverEventLog_AddReg]
|
||||
HKR,,EventMessageFile,REG_EXPAND_SZ,"%SystemRoot%\System32\IoLogMsg.dll;%SystemRoot%\System32\drivers\ircomm2k.sys"
|
||||
HKR,,TypesSupported,REG_DWORD,7
|
||||
|
||||
|
||||
[Strings]
|
||||
|
||||
;
|
||||
; Non-Localizable Strings
|
||||
;
|
||||
|
||||
REG_SZ = 0x00000000
|
||||
REG_MULTI_SZ = 0x00010000
|
||||
REG_EXPAND_SZ = 0x00020000
|
||||
REG_BINARY = 0x00000001
|
||||
REG_DWORD = 0x00010001
|
||||
SERVICEROOT = "System\CurrentControlSet\Services"
|
||||
UNINSTALL_KEY = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\IrCOMM2k"
|
||||
|
||||
;
|
||||
; Localizable Strings
|
||||
;
|
||||
|
||||
JK = "Jan Kiszka"
|
||||
JK.DeviceDescIrCOMM = "Virtueller Infrarot-Kommunikationsanschluss"
|
||||
IrCOMM2k.DrvName = "Virtueller Infrarot-Kommunikationsanschluss"
|
||||
;IrCOMM2k.SvcName = "Virtueller Infrarot-Kommunikationsanschlu<6C>, Dienstprogramm"
|
||||
;IrCOMM2k.SvcDesc = "Bildet <20>ber Infarot einen Kommunikationsanschlu<6C> nach."
|
BIN
altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys
Normal file
BIN
altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys
Normal file
Binary file not shown.
181
altosui/Instdrv/NSIS/Includes/java.nsh
Normal file
181
altosui/Instdrv/NSIS/Includes/java.nsh
Normal file
@@ -0,0 +1,181 @@
|
||||
!include WordFunc.nsh
|
||||
|
||||
; Definitions for Java Detection
|
||||
|
||||
!define JAVA_VERSION "6.0"
|
||||
|
||||
Function GetFileVersion
|
||||
!define GetFileVersion `!insertmacro GetFileVersionCall`
|
||||
|
||||
!macro GetFileVersionCall _FILE _RESULT
|
||||
Push `${_FILE}`
|
||||
Call GetFileVersion
|
||||
Pop ${_RESULT}
|
||||
!macroend
|
||||
|
||||
Exch $0
|
||||
Push $1
|
||||
Push $2
|
||||
Push $3
|
||||
Push $4
|
||||
Push $5
|
||||
Push $6
|
||||
ClearErrors
|
||||
|
||||
GetDllVersion '$0' $1 $2
|
||||
IfErrors error
|
||||
IntOp $3 $1 >> 16
|
||||
IntOp $3 $3 & 0x0000FFFF
|
||||
IntOp $4 $1 & 0x0000FFFF
|
||||
IntOp $5 $2 >> 16
|
||||
IntOp $5 $5 & 0x0000FFFF
|
||||
IntOp $6 $2 & 0x0000FFFF
|
||||
StrCpy $0 '$3.$4.$5.$6'
|
||||
goto end
|
||||
|
||||
error:
|
||||
SetErrors
|
||||
StrCpy $0 ''
|
||||
|
||||
end:
|
||||
Pop $6
|
||||
Pop $5
|
||||
Pop $4
|
||||
Pop $3
|
||||
Pop $2
|
||||
Pop $1
|
||||
Exch $0
|
||||
FunctionEnd
|
||||
|
||||
Function openLinkNewWindow
|
||||
Push $3
|
||||
Exch
|
||||
Push $2
|
||||
Exch
|
||||
Push $1
|
||||
Exch
|
||||
Push $0
|
||||
Exch
|
||||
|
||||
ReadRegStr $1 HKCU "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.html\UserChoice" "Progid"
|
||||
IfErrors iexplore
|
||||
|
||||
Goto foundbrowser
|
||||
iexplore:
|
||||
StrCpy $1 "IE.AssocFile.HTM"
|
||||
|
||||
foundbrowser:
|
||||
|
||||
StrCpy $2 "\shell\open\command"
|
||||
|
||||
StrCpy $3 $1$2
|
||||
|
||||
ReadRegStr $0 HKCR $3 ""
|
||||
|
||||
# Get browser path
|
||||
DetailPrint $0
|
||||
|
||||
StrCpy $2 '"'
|
||||
StrCpy $1 $0 1
|
||||
StrCmp $1 $2 +2 # if path is not enclosed in " look for space as final char
|
||||
StrCpy $2 ' '
|
||||
StrCpy $3 1
|
||||
loop:
|
||||
StrCpy $1 $0 1 $3
|
||||
DetailPrint $1
|
||||
StrCmp $1 $2 found
|
||||
StrCmp $1 "" found
|
||||
IntOp $3 $3 + 1
|
||||
Goto loop
|
||||
|
||||
found:
|
||||
StrCpy $1 $0 $3
|
||||
StrCmp $2 " " +2
|
||||
StrCpy $1 '$1"'
|
||||
|
||||
Pop $0
|
||||
Exec '$1 $0'
|
||||
Pop $0
|
||||
Pop $1
|
||||
Pop $2
|
||||
Pop $3
|
||||
FunctionEnd
|
||||
|
||||
!macro _OpenURL URL
|
||||
Push "${URL}"
|
||||
Call openLinkNewWindow
|
||||
!macroend
|
||||
|
||||
!define OpenURL '!insertmacro "_OpenURL"'
|
||||
|
||||
Function DoDetectJRE
|
||||
|
||||
DetailPrint "Desired Java version ${JAVA_VERSION}"
|
||||
|
||||
SearchPath $0 javaw.exe
|
||||
IfErrors no
|
||||
|
||||
DetailPrint "Detected java in $0"
|
||||
|
||||
${GetFileVersion} "$0" $1
|
||||
IfErrors no
|
||||
|
||||
DetailPrint "Java version $1"
|
||||
|
||||
${VersionCompare} $1 ${JAVA_VERSION} $2
|
||||
IntCmp $2 1 yes yes old
|
||||
|
||||
yes:
|
||||
StrCpy $0 2
|
||||
Goto done
|
||||
|
||||
old:
|
||||
StrCpy $0 1
|
||||
Goto done
|
||||
|
||||
no:
|
||||
StrCpy $0 0
|
||||
Goto done
|
||||
|
||||
done:
|
||||
|
||||
FunctionEnd
|
||||
|
||||
var dialog
|
||||
var hwnd
|
||||
var null
|
||||
|
||||
var install
|
||||
var quit
|
||||
var skip
|
||||
|
||||
Function GetJRE
|
||||
${OpenURL} "adoptium.net"
|
||||
MessageBox MB_OK "Click OK to continue after completing the Java Install."
|
||||
FunctionEnd
|
||||
|
||||
Function DetectJRE
|
||||
|
||||
Call DoDetectJRE
|
||||
|
||||
IntCmp $0 1 ask_old ask_no yes
|
||||
|
||||
ask_no:
|
||||
StrCpy $0 "Cannot find Java. Download and install?"
|
||||
Goto ask
|
||||
|
||||
ask_old:
|
||||
StrCpy $0 "Java version appears to be too old. Download and install?"
|
||||
Goto ask
|
||||
|
||||
ask:
|
||||
MessageBox MB_YESNOCANCEL $0 IDYES do_java IDNO skip_java
|
||||
|
||||
do_java:
|
||||
Call GetJRE
|
||||
|
||||
|
||||
skip_java:
|
||||
yes:
|
||||
|
||||
FunctionEnd
|
14
altosui/Instdrv/NSIS/Includes/refresh-sh.nsh
Normal file
14
altosui/Instdrv/NSIS/Includes/refresh-sh.nsh
Normal file
@@ -0,0 +1,14 @@
|
||||
!define SHCNE_ASSOCCHANGED 0x08000000
|
||||
!define SHCNF_IDLIST 0
|
||||
|
||||
Function RefreshShellIcons
|
||||
; By jerome tremblay - april 2003
|
||||
${DisableX64FSRedirection}
|
||||
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (${SHCNE_ASSOCCHANGED}, ${SHCNF_IDLIST}, 0, 0)'
|
||||
FunctionEnd
|
||||
|
||||
Function un.RefreshShellIcons
|
||||
; By jerome tremblay - april 2003
|
||||
${DisableX64FSRedirection}
|
||||
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (${SHCNE_ASSOCCHANGED}, ${SHCNF_IDLIST}, 0, 0)'
|
||||
FunctionEnd
|
191
altosui/Makefile-standalone
Normal file
191
altosui/Makefile-standalone
Normal file
@@ -0,0 +1,191 @@
|
||||
.SUFFIXES: .java .class
|
||||
|
||||
CLASSPATH=classes:./*:/usr/share/java/*
|
||||
CLASSFILES=\
|
||||
Altos.class \
|
||||
AltosChannelMenu.class \
|
||||
AltosConfigFC.class \
|
||||
AltosConfigFCUI.class \
|
||||
AltosConvert.class \
|
||||
AltosCRCException.class \
|
||||
AltosCSV.class \
|
||||
AltosCSVUI.class \
|
||||
AltosDebug.class \
|
||||
AltosEepromDownload.class \
|
||||
AltosEepromMonitor.class \
|
||||
AltosEepromReader.class \
|
||||
AltosEepromRecord.class \
|
||||
AltosFile.class \
|
||||
AltosFlash.class \
|
||||
AltosFlashUI.class \
|
||||
AltosFlightInfoTableModel.class \
|
||||
AltosFlightStatusTableModel.class \
|
||||
AltosGPS.class \
|
||||
AltosGreatCircle.class \
|
||||
AltosHexfile.class \
|
||||
AltosLine.class \
|
||||
AltosInfoTable.class \
|
||||
AltosLog.class \
|
||||
AltosLogfileChooser.class \
|
||||
AltosParse.class \
|
||||
AltosPreferences.class \
|
||||
AltosReader.class \
|
||||
AltosRecord.class \
|
||||
AltosSerialMonitor.class \
|
||||
AltosSerial.class \
|
||||
AltosState.class \
|
||||
AltosStatusTable.class \
|
||||
AltosTelemetry.class \
|
||||
AltosTelemetryReader.class \
|
||||
AltosUI.class \
|
||||
AltosDevice.class \
|
||||
AltosDeviceDialog.class \
|
||||
AltosRomconfig.class \
|
||||
AltosRomconfigUI.class \
|
||||
AltosVoice.class
|
||||
|
||||
JAVA_ICONS=\
|
||||
../icon/altus-metrum-16.png \
|
||||
../icon/altus-metrum-32.png \
|
||||
../icon/altus-metrum-48.png \
|
||||
../icon/altus-metrum-64.png \
|
||||
../icon/altus-metrum-128.png \
|
||||
../icon/altus-metrum-256.png
|
||||
|
||||
WINDOWS_ICON=../icon/altus-metrum.ico
|
||||
|
||||
# where altosui.jar gets installed
|
||||
ALTOSLIB=/usr/share/java
|
||||
|
||||
# where freetts.jar is to be found
|
||||
FREETTSLIB=/usr/share/java
|
||||
|
||||
# all of the freetts files
|
||||
FREETTSJAR= \
|
||||
$(FREETTSLIB)/cmudict04.jar \
|
||||
$(FREETTSLIB)/cmulex.jar \
|
||||
$(FREETTSLIB)/cmu_time_awb.jar \
|
||||
$(FREETTSLIB)/cmutimelex.jar \
|
||||
$(FREETTSLIB)/cmu_us_kal.jar \
|
||||
$(FREETTSLIB)/en_us.jar \
|
||||
$(FREETTSLIB)/freetts.jar
|
||||
|
||||
# The current hex files
|
||||
HEXLIB=../src
|
||||
HEXFILES = \
|
||||
$(HEXLIB)/telemetrum-v1.0.ihx \
|
||||
$(HEXLIB)/teledongle-v0.2.ihx
|
||||
|
||||
JAVAFLAGS=-Xlint:unchecked -Xlint:deprecation
|
||||
|
||||
ALTOSUIJAR = altosui.jar
|
||||
FATJAR = fat/altosui.jar
|
||||
|
||||
OS:=$(shell uname)
|
||||
|
||||
LINUX_APP=altosui
|
||||
|
||||
DARWIN_ZIP=Altos-Mac.zip
|
||||
|
||||
WINDOWS_EXE=Altos-Windows.exe
|
||||
|
||||
LINUX_TGZ=Altos-Linux.tgz
|
||||
|
||||
all: altosui.jar $(LINUX_APP)
|
||||
fat: altosui.jar $(LINUX_APP) $(DARWIN_ZIP) $(WINDOWS_EXE) $(LINUX_TGZ)
|
||||
|
||||
$(CLASSFILES):
|
||||
|
||||
.java.class:
|
||||
javac -encoding UTF8 -classpath "$(CLASSPATH)" $(JAVAFLAGS) $*.java
|
||||
|
||||
altosui.jar: classes/images classes/altosui classes/libaltosJNI $(CLASSFILES) Manifest.txt
|
||||
cd ./classes && jar cfm ../$@ altosui/Manifest.txt images/* altosui/*.class libaltosJNI/*.class
|
||||
|
||||
Manifest.txt: Makefile $(CLASSFILES)
|
||||
echo 'Main-Class: altosui.AltosUI' > $@
|
||||
echo "Class-Path: $(FREETTSLIB)/freetts.jar" >> $@
|
||||
|
||||
classes/altosui:
|
||||
mkdir -p classes
|
||||
ln -sf .. classes/altosui
|
||||
|
||||
classes/libaltosJNI:
|
||||
mkdir -p classes
|
||||
ln -sf ../libaltos/libaltosJNI classes/libaltosJNI
|
||||
|
||||
classes/images:
|
||||
mkdir -p classes/images
|
||||
ln -sf ../$(JAVA_ICONS) classes/images
|
||||
|
||||
altosui:
|
||||
echo "#!/bin/sh" > $@
|
||||
echo "exec java -Djava.library.path=/usr/lib/altos -jar /usr/share/java/altosui.jar" >> $@
|
||||
chmod +x ./altosui
|
||||
|
||||
fat/altosui:
|
||||
echo "#!/bin/sh" > $@
|
||||
echo 'ME=`which "$0"`' >> $@
|
||||
echo 'DIR=`dirname "$ME"`' >> $@
|
||||
echo 'exec java -Djava.library.path="$$DIR" -jar "$$DIR"/altosui.jar' >> $@
|
||||
chmod +x $@
|
||||
|
||||
fat/altosui.jar: $(CLASSFILES) $(JAVA_ICONS) fat/classes/Manifest.txt
|
||||
mkdir -p fat/classes
|
||||
test -L fat/classes/altosui || ln -sf ../.. fat/classes/altosui
|
||||
mkdir -p fat/classes/images
|
||||
cp $(JAVA_ICONS) fat/classes/images
|
||||
test -L fat/classes/libaltosJNI || ln -sf ../../libaltos/libaltosJNI fat/classes/libaltosJNI
|
||||
cd ./fat/classes && jar cfm ../../$@ Manifest.txt images/* altosui/*.class libaltosJNI/*.class
|
||||
|
||||
fat/classes/Manifest.txt: $(CLASSFILES) Makefile
|
||||
mkdir -p fat/classes
|
||||
echo 'Main-Class: altosui.AltosUI' > $@
|
||||
echo "Class-Path: freetts.jar" >> $@
|
||||
|
||||
install: altosui.jar altosui
|
||||
install -m 0644 altosui.jar $(DESTDIR)/usr/share/java/altosui.jar
|
||||
install -m 0644 altosui.1 $(DESTDIR)/usr/share/man/man1/altosui.1
|
||||
install altosui $(DESTDIR)/usr/bin/altosui
|
||||
|
||||
clean:
|
||||
rm -f *.class altosui.jar
|
||||
rm -f AltosUI.app/Contents/Resources/Java/*
|
||||
rm -rf classes
|
||||
rm -rf windows linux
|
||||
|
||||
distclean: clean
|
||||
rm -f $(DARWIN_ZIP) $(WINDOWS_EXE) $(LINUX_TGZ)
|
||||
rm -rf darwin fat
|
||||
|
||||
FAT_FILES=$(FATJAR) $(FREETTSJAR) $(HEXFILES)
|
||||
|
||||
LINUX_FILES=$(FAT_FILES) libaltos/libaltos.so fat/altosui
|
||||
$(LINUX_TGZ): $(LINUX_FILES)
|
||||
rm -f $@
|
||||
mkdir -p linux/AltOS
|
||||
rm -f linux/AltOS/*
|
||||
cp $(LINUX_FILES) linux/AltOS
|
||||
cd linux && tar czf ../$@ AltOS
|
||||
|
||||
DARWIN_RESOURCES=$(FATJAR) $(FREETTSJAR) libaltos/libaltos.dylib
|
||||
DARWIN_EXTRA=$(HEXFILES)
|
||||
DARWIN_FILES=$(DARWIN_RESOURCES) $(DARWIN_EXTRA)
|
||||
|
||||
$(DARWIN_ZIP): $(DARWIN_FILES)
|
||||
rm -f $@
|
||||
cp -a AltosUI.app darwin/
|
||||
mkdir -p darwin/AltosUI.app/Contents/Resources/Java
|
||||
cp $(DARWIN_RESOURCES) darwin/AltosUI.app/Contents/Resources/Java
|
||||
mkdir -p darwin/AltOS
|
||||
cp $(DARWIN_EXTRA) darwin/AltOS
|
||||
cd darwin && zip -r ../$@ AltosUI.app AltOS
|
||||
|
||||
WINDOWS_FILES = $(FAT_FILES) libaltos/altos.dll ../altusmetrum.inf $(WINDOWS_ICON)
|
||||
|
||||
$(WINDOWS_EXE): $(WINDOWS_FILES) altos-windows.nsi
|
||||
rm -f $@
|
||||
mkdir -p windows/AltOS
|
||||
rm -f windows/AltOS/*
|
||||
cp $(WINDOWS_FILES) windows/AltOS
|
||||
makensis altos-windows.nsi
|
423
altosui/Makefile.am
Normal file
423
altosui/Makefile.am
Normal file
@@ -0,0 +1,423 @@
|
||||
# location of code signing key, et al
|
||||
|
||||
JAVAROOT=classes
|
||||
AM_JAVACFLAGS=$(JAVAC_VERSION_FLAGS) -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked
|
||||
|
||||
man_MANS=altosui.1
|
||||
|
||||
altoslibdir=$(libdir)/altos
|
||||
|
||||
CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="$(JAVAROOT):../altoslib/*:../altosuilib/*:../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar:$(FREETTS)/freetts.jar"
|
||||
|
||||
bin_SCRIPTS=altosui
|
||||
|
||||
altosui_JAVA = \
|
||||
AltosAscent.java \
|
||||
AltosChannelMenu.java \
|
||||
AltosCompanionInfo.java \
|
||||
AltosConfigFC.java \
|
||||
AltosConfigFCUI.java \
|
||||
AltosConfigPyroUI.java \
|
||||
AltosConfigureUI.java \
|
||||
AltosConfigTD.java \
|
||||
AltosConfigTDUI.java \
|
||||
AltosDescent.java \
|
||||
AltosFlightStatus.java \
|
||||
AltosFlightStatusUpdate.java \
|
||||
AltosFlightUI.java \
|
||||
Altos.java \
|
||||
AltosIdleMonitorUI.java \
|
||||
AltosIgniteUI.java \
|
||||
AltosIgnitor.java \
|
||||
AltosLaunch.java \
|
||||
AltosLaunchUI.java \
|
||||
AltosLanded.java \
|
||||
AltosPad.java \
|
||||
AltosUI.java \
|
||||
AltosGraphUI.java
|
||||
|
||||
JFREECHART_CLASS= \
|
||||
jfreechart.jar
|
||||
|
||||
JCOMMON_CLASS=\
|
||||
jcommon.jar
|
||||
|
||||
FREETTS_CLASS= \
|
||||
cmudict04.jar \
|
||||
cmulex.jar \
|
||||
cmu_time_awb.jar \
|
||||
cmutimelex.jar \
|
||||
cmu_us_kal.jar \
|
||||
en_us.jar \
|
||||
freetts.jar
|
||||
|
||||
ALTOSLIB_CLASS=\
|
||||
altoslib_$(ALTOSLIB_VERSION).jar
|
||||
|
||||
ALTOSUILIB_CLASS=\
|
||||
altosuilib_$(ALTOSUILIB_VERSION).jar
|
||||
|
||||
if MULTI_ARCH
|
||||
LIBALTOS_LINUX=libaltos_i686.so libaltos_amd64.so libaltos_aarch64.so libaltos_armel.so libaltos_armhf.so
|
||||
else
|
||||
LIBALTOS_LINUX=libaltos.so
|
||||
endif
|
||||
|
||||
LIBALTOS= \
|
||||
$(LIBALTOS_LINUX) \
|
||||
libaltos.dylib \
|
||||
altos.dll \
|
||||
altos64.dll
|
||||
|
||||
desktopdir = $(datadir)/applications
|
||||
desktop_file = altusmetrum-altosui.desktop
|
||||
desktop_SCRIPTS = $(desktop_file)
|
||||
|
||||
JAR=altosui.jar
|
||||
|
||||
FATJAR=altosui-fat.jar
|
||||
|
||||
# Icons
|
||||
ICONDIR=../icon
|
||||
|
||||
JAVA_ICONS=\
|
||||
$(ICONDIR)/altusmetrum-altosui-16.png \
|
||||
$(ICONDIR)/altusmetrum-altosui-32.png \
|
||||
$(ICONDIR)/altusmetrum-altosui-48.png \
|
||||
$(ICONDIR)/altusmetrum-altosui-64.png \
|
||||
$(ICONDIR)/altusmetrum-altosui-128.png\
|
||||
$(ICONDIR)/altusmetrum-altosui-256.png
|
||||
|
||||
# icon base names for jar
|
||||
ICONJAR= \
|
||||
-C $(ICONDIR) altusmetrum-altosui-16.png \
|
||||
-C $(ICONDIR) altusmetrum-altosui-32.png \
|
||||
-C $(ICONDIR) altusmetrum-altosui-48.png \
|
||||
-C $(ICONDIR) altusmetrum-altosui-64.png \
|
||||
-C $(ICONDIR) altusmetrum-altosui-128.png\
|
||||
-C $(ICONDIR) altusmetrum-altosui-256.png
|
||||
|
||||
WINDOWS_ICONS =\
|
||||
$(ICONDIR)/altusmetrum-altosui.ico \
|
||||
$(ICONDIR)/altusmetrum-altosui.exe
|
||||
$(ICONDIR)/application-vnd.altusmetrum.eeprom.ico \
|
||||
$(ICONDIR)/application-vnd.altusmetrum.eeprom.exe \
|
||||
$(ICONDIR)/application-vnd.altusmetrum.telemetry.ico \
|
||||
$(ICONDIR)/application-vnd.altusmetrum.telemetry.exe
|
||||
|
||||
MACOSX_ICONS =\
|
||||
$(ICONDIR)/altusmetrum-altosui.icns \
|
||||
$(ICONDIR)/application-vnd.altusmetrum.eeprom.icns \
|
||||
$(ICONDIR)/application-vnd.altusmetrum.telemetry.icns
|
||||
|
||||
LINUX_ICONS =\
|
||||
$(ICONDIR)/altusmetrum-altosui.svg \
|
||||
$(ICONDIR)/application-vnd.altusmetrum.eeprom.svg \
|
||||
$(ICONDIR)/application-vnd.altusmetrum.telemetry.svg
|
||||
|
||||
LINUX_MIMETYPE =\
|
||||
$(ICONDIR)/org-altusmetrum-mimetypes.xml
|
||||
|
||||
# Firmware
|
||||
FIRMWARE_TD_3_0=$(top_srcdir)/src/teledongle-v3.0/teledongle-v3.0-$(VERSION).ihx
|
||||
FIRMWARE_TD=$(FIRMWARE_TD_3_0)
|
||||
|
||||
FIRMWARE_TM_2_0=$(top_srcdir)/src/telemetrum-v2.0/telemetrum-v2.0-$(VERSION).ihx
|
||||
FIRMWARE_TM_3_0=$(top_srcdir)/src/telemetrum-v3.0/telemetrum-v3.0-$(VERSION).ihx
|
||||
FIRMWARE_TM_4_0=$(top_srcdir)/src/telemetrum-v4.0/telemetrum-v4.0-$(VERSION).ihx
|
||||
FIRMWARE_TM=$(FIRMWARE_TM_2_0) $(FIRMWARE_TM_3_0) $(FIRMWARE_TM_4_0)
|
||||
|
||||
FIRMWARE_TELEMINI_3_0=$(top_srcdir)/src/telemini-v3.0/telemini-v3.0-$(VERSION).ihx
|
||||
FIRMWARE_TELEMINI=$(FIRMWARE_TELEMINI_3_0)
|
||||
|
||||
FIRMWARE_TBT_3_0=$(top_srcdir)/src/telebt-v3.0/telebt-v3.0-$(VERSION).ihx
|
||||
FIRMWARE_TBT_4_0=$(top_srcdir)/src/telebt-v4.0/telebt-v4.0-$(VERSION).ihx
|
||||
FIRMWARE_TBT=$(FIRMWARE_TBT_3_0) $(FIRMWARE_TBT_4_0)
|
||||
|
||||
FIRMWARE_TMEGA_1_0=$(top_srcdir)/src/telemega-v1.0/telemega-v1.0-$(VERSION).ihx
|
||||
FIRMWARE_TMEGA_2_0=$(top_srcdir)/src/telemega-v2.0/telemega-v2.0-$(VERSION).ihx
|
||||
FIRMWARE_TMEGA_3_0=$(top_srcdir)/src/telemega-v3.0/telemega-v3.0-$(VERSION).ihx
|
||||
FIRMWARE_TMEGA_4_0=$(top_srcdir)/src/telemega-v4.0/telemega-v4.0-$(VERSION).ihx
|
||||
FIRMWARE_TMEGA_5_0=$(top_srcdir)/src/telemega-v5.0/telemega-v5.0-$(VERSION).ihx
|
||||
FIRMWARE_TMEGA_6_0=$(top_srcdir)/src/telemega-v6.0/telemega-v6.0-$(VERSION).ihx
|
||||
FIRMWARE_TMEGA=$(FIRMWARE_TMEGA_1_0) $(FIRMWARE_TMEGA_2_0) $(FIRMWARE_TMEGA_3_0) $(FIRMWARE_TMEGA_4_0) $(FIRMWARE_TMEGA_5_0) $(FIRMWARE_TMEGA_6_0)
|
||||
|
||||
FIRMWARE_EMINI_1_0=$(top_srcdir)/src/easymini-v1.0/easymini-v1.0-$(VERSION).ihx
|
||||
FIRMWARE_EMINI_2_0=$(top_srcdir)/src/easymini-v2.0/easymini-v2.0-$(VERSION).ihx
|
||||
FIRMWARE_EMINI_3_0=$(top_srcdir)/src/easymini-v3.0/easymini-v3.0-$(VERSION).ihx
|
||||
FIRMWARE_EMINI=$(FIRMWARE_EMINI_1_0) $(FIRMWARE_EMINI_2_0) $(FIRMWARE_EMINI_3_0)
|
||||
|
||||
FIRMWARE_EMEGA_1_0=$(top_srcdir)/src/easymega-v1.0/easymega-v1.0-$(VERSION).ihx
|
||||
FIRMWARE_EMEGA_2_0=$(top_srcdir)/src/easymega-v2.0/easymega-v2.0-$(VERSION).ihx
|
||||
FIRMWARE_EMEGA=$(FIRMWARE_EMEGA_1_0) $(FIRMWARE_EMEGA_2_0)
|
||||
|
||||
FIRMWARE_EMOTOR_3=$(top_srcdir)/src/easymotor-v3/easymotor-v3-$(VERSION).ihx
|
||||
FIRMWARE_EMOTOR=$(FIRMWARE_EMOTOR_3)
|
||||
|
||||
FIRMWARE_ETIMER_1=$(top_srcdir)/src/easytimer-v1/easytimer-v1-$(VERSION).ihx
|
||||
FIRMWARE_ETIMER_2=$(top_srcdir)/src/easytimer-v2/easytimer-v2-$(VERSION).ihx
|
||||
FIRMWARE_ETIMER=$(FIRMWARE_ETIMER_1) $(FIRMWARE_ETIMER_2)
|
||||
|
||||
FIRMWARE_TGPS_1_0=$(top_srcdir)/src/telegps-v1.0/telegps-v1.0-$(VERSION).ihx
|
||||
FIRMWARE_TGPS_2_0=$(top_srcdir)/src/telegps-v2.0/telegps-v2.0-$(VERSION).ihx
|
||||
FIRMWARE_TGPS_3_0=$(top_srcdir)/src/telegps-v3.0/telegps-v3.0-$(VERSION).ihx
|
||||
FIRMWARE_TGPS=$(FIRMWARE_TGPS_1_0) $(FIRMWARE_TGPS_2_0) $(FIRMWARE_TGPS_3_0)
|
||||
|
||||
FIRMWARE_TLCO_2_0=$(top_srcdir)/src/telelco-v2.0/telelco-v2.0-$(VERSION).ihx
|
||||
FIRMWARE_TLCO=$(FIRMWARE_TLCO_2_0)
|
||||
|
||||
FIRMWARE_TFIRE8_1_0=$(top_srcdir)/src/telefireeight-v1.0/telefireeight-v1.0-$(VERSION).ihx
|
||||
FIRMWARE_TFIRE8_2_0=$(top_srcdir)/src/telefireeight-v2.0/telefireeight-v2.0-$(VERSION).ihx
|
||||
FIRMWARE_TFIRE8=$(FIRMWARE_TFIRE8_1_0) $(FIRMWARE_TFIRE8_2_0)
|
||||
|
||||
FIRMWARE=$(FIRMWARE_TM) $(FIRMWARE_TELEMINI) $(FIRMWARE_TD) $(FIRMWARE_TBT) $(FIRMWARE_TMEGA) $(FIRMWARE_EMINI) $(FIRMWARE_TGPS) $(FIRMWARE_EMEGA) $(FIRMWARE_EMOTOR) $(FIRMWARE_ETIMER) $(FIRMWARE_TLCO) $(FIRMWARE_TFIRE8)
|
||||
|
||||
ALTUSMETRUM_DOC=$(top_srcdir)/doc/altusmetrum.pdf
|
||||
ALTOS_DOC=$(top_srcdir)/doc/altos.pdf
|
||||
TELEMETRY_DOC=$(top_srcdir)/doc/telemetry.pdf
|
||||
MOTORTEST_DOC=$(top_srcdir)/doc/motortest.pdf
|
||||
TEMPLATE_DOC=\
|
||||
$(top_srcdir)/doc/telemetrum-outline.pdf \
|
||||
$(top_srcdir)/doc/easymini-outline.pdf \
|
||||
$(top_srcdir)/doc/telemega-outline.pdf \
|
||||
$(top_srcdir)/doc/telemini-v1-outline.pdf \
|
||||
$(top_srcdir)/doc/telemini-v3-outline.pdf
|
||||
|
||||
DOC=$(ALTUSMETRUM_DOC) $(ALTOS_DOC) $(TELEMETRY_DOC) $(MOTORTEST_DOC) $(TEMPLATE_DOC)
|
||||
|
||||
# Distribution targets
|
||||
LINUX_DIST=Altos-Linux-$(VERSION).tar.bz2
|
||||
LINUX_SH=Altos-Linux-$(VERSION).sh
|
||||
MACOSX_DIST=Altos-Mac-$(VERSION).dmg
|
||||
WINDOWS_DIST=Altos-Windows-$(VERSION_DASH).exe
|
||||
MDWN=$(VERSION).mdwn
|
||||
MDWNTMPL=mdwn.tmpl
|
||||
|
||||
FAT_FILES=$(FATJAR) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS)
|
||||
|
||||
LINUX_LIBS=$(LIBALTOS_LINUX)
|
||||
|
||||
LINUX_FILES=$(FAT_FILES) $(LINUX_LIBS) $(FIRMWARE) $(DOC) $(desktop_file).in $(LINUX_ICONS) $(LINUX_MIMETYPE)
|
||||
LINUX_EXTRA=altosui-fat
|
||||
|
||||
MACOSX_INFO_PLIST=Info.plist
|
||||
MACOSX_INSTALL=install-macosx ask-pass
|
||||
MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(DOC) ReadMe-Mac.rtf $(MACOSX_ICONS) $(MACOSX_INSTALL)
|
||||
MACOSX_EXTRA=$(FIRMWARE)
|
||||
|
||||
WINDOWS_FILES=$(FAT_FILES) $(FIRMWARE) altos.dll altos64.dll $(top_srcdir)/altusmetrum.inf $(top_srcdir)/altusmetrum.cat $(WINDOWS_ICONS)
|
||||
|
||||
all-local: classes/altosui $(JAR) altosui altosui-test altosui-jdb $(MDWN)
|
||||
|
||||
clean-local:
|
||||
-rm -rf classes $(JAR) $(FATJAR) \
|
||||
Altos-Linux-*.tar.bz2 Altos-Linux-*.sh Altos-Mac-*.dmg Altos-Windows-*.exe \
|
||||
windows altoslib_*.jar altosuilib_*.jar $(FREETTS_CLASS) \
|
||||
$(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log altos-windows.nsi \
|
||||
altosui altosui-test altosui-jdb macosx linux *.desktop *.mdwn
|
||||
|
||||
EXTRA_DIST = $(desktop_file).in
|
||||
|
||||
$(desktop_file): $(desktop_file).in
|
||||
sed -e 's#%bindir%#@bindir@#' -e 's#%icondir%#$(datadir)/icons/hicolor/scalable/apps#' ${srcdir}/$(desktop_file).in > $@
|
||||
chmod +x $@
|
||||
|
||||
if FATINSTALL
|
||||
|
||||
FATTARGET=$(FATDIR)/AltOS/releases/$(VERSION)
|
||||
|
||||
LINUX_SH_TARGET=$(FATTARGET)/$(LINUX_SH)
|
||||
MACOSX_DIST_TARGET=$(FATTARGET)/$(MACOSX_DIST)
|
||||
WINDOWS_DIST_TARGET=$(FATTARGET)/$(WINDOWS_DIST)
|
||||
MDWN_TARGET=$(FATDIR)/AltOS/releases/$(MDWN)
|
||||
RELNOTES=release-notes-$(VERSION).html
|
||||
RELNOTES_SRC=$(top_builddir)/doc/$(RELNOTES)
|
||||
RELNOTES_TARGET=$(FATTARGET)/$(RELNOTES)
|
||||
|
||||
fat-install: fat $(LINUX_SH_TARGET) $(MACOSX_DIST_TARGET) $(WINDOWS_DIST_TARGET) $(MDWN_TARGET) $(RELNOTES_TARGET)
|
||||
|
||||
$(LINUX_SH_TARGET): $(LINUX_SH)
|
||||
mkdir -p $(FATTARGET)
|
||||
cp -p $< $@
|
||||
|
||||
$(MACOSX_DIST_TARGET): $(MACOSX_DIST)
|
||||
mkdir -p $(FATTARGET)
|
||||
cp -p $< $@
|
||||
|
||||
$(WINDOWS_DIST_TARGET): $(WINDOWS_DIST)
|
||||
mkdir -p $(FATTARGET)
|
||||
cp -p $< $@
|
||||
|
||||
$(MDWN_TARGET): $(MDWN)
|
||||
mkdir -p $(FATTARGET)
|
||||
cp -p $< $@
|
||||
|
||||
$(RELNOTES_TARGET): $(RELNOTES_SRC)
|
||||
mkdir -p $(FATTARGET)
|
||||
sh $(top_srcdir)/doc/install-html -d $(FATTARGET) $(RELNOTES_SRC)
|
||||
|
||||
endif
|
||||
|
||||
$(MDWN): $(MDWNTMPL)
|
||||
sed -e 's/%version%/$(VERSION)/g' -e 's/%version_dash%/$(VERSION_DASH)/g' $(MDWNTMPL) > $@
|
||||
|
||||
fat: $(LINUX_DIST) $(LINUX_SH) $(MACOSX_DIST) $(WINDOWS_DIST)
|
||||
|
||||
altosuidir=$(datadir)/java
|
||||
|
||||
install-altosuiJAVA: altosui.jar
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(altosuidir)" || $(MKDIR_P) "$(DESTDIR)$(altosuidir)"
|
||||
echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(altosuidir)/altosui.jar'"; \
|
||||
$(INSTALL_DATA) "$<" "$(DESTDIR)$(altosuidir)"
|
||||
|
||||
classes/altosui:
|
||||
mkdir -p classes/altosui
|
||||
|
||||
$(JAR): classaltosui.stamp Manifest.txt $(JAVA_ICONS) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) build-libaltos
|
||||
jar cfm $@ Manifest.txt \
|
||||
$(ICONJAR) \
|
||||
-C classes altosui \
|
||||
-C ../libaltos libaltosJNI
|
||||
if STRIP_NONDETERMINISM
|
||||
$(STRIP_NONDETERMINISM) $@
|
||||
endif
|
||||
|
||||
$(FATJAR): classaltosui.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) $(JAVA_ICONS)
|
||||
jar cfm $@ Manifest-fat.txt \
|
||||
$(ICONJAR) \
|
||||
-C classes altosui \
|
||||
-C ../libaltos libaltosJNI
|
||||
if STRIP_NONDETERMINISM
|
||||
$(STRIP_NONDETERMINISM) $@
|
||||
endif
|
||||
|
||||
Manifest.txt: Makefile
|
||||
echo 'Main-Class: altosui.AltosUI' > $@
|
||||
echo "Class-Path: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS)/freetts.jar $(JCOMMON)/jcommon.jar $(JFREECHART)/jfreechart.jar" >> $@
|
||||
|
||||
Manifest-fat.txt:
|
||||
echo 'Main-Class: altosui.AltosUI' > $@
|
||||
echo "Class-Path: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) freetts.jar jcommon.jar jfreechart.jar" >> $@
|
||||
|
||||
altosui: Makefile
|
||||
echo "#!/bin/sh" > $@
|
||||
echo 'exec java -Djava.library.path="$(altoslibdir)" -jar "$(altosuidir)/altosui.jar" "$$@"' >> $@
|
||||
chmod +x $@
|
||||
|
||||
altosui-test: Makefile
|
||||
echo '#!/bin/sh' > $@
|
||||
echo 'dir="$$(dirname $$0)"' >> $@
|
||||
echo 'cd "$$dir"' >> $@
|
||||
echo 'altosui="$$(pwd -P)"' >> $@
|
||||
echo 'altos="$$(dirname $$altosui)"' >> $@
|
||||
echo 'exec java -Djava.library.path="$$altos/libaltos/.libs" -jar "$$altosui/altosui.jar" "$$@"' >> $@
|
||||
chmod +x $@
|
||||
|
||||
altosui-jdb: Makefile
|
||||
echo "#!/bin/sh" > $@
|
||||
echo 'exec jdb -classpath "classes:./*:../libaltos:$(FREETTS)/freetts.jar:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="../libaltos/.libs" altosui/AltosUI "$$@"' >> $@
|
||||
chmod +x $@
|
||||
|
||||
libaltos.so: build-libaltos
|
||||
-rm -f "$@"
|
||||
$(LN_S) ../libaltos/.libs/"$@" .
|
||||
|
||||
libaltos_i686.so: build-libaltos
|
||||
-rm -f "$@"
|
||||
$(LN_S) ../libaltos/.libs/"$@" .
|
||||
|
||||
libaltos_amd64.so: build-libaltos
|
||||
-rm -f "$@"
|
||||
$(LN_S) ../libaltos/.libs/"$@" .
|
||||
|
||||
libaltos_aarch64.so: build-libaltos
|
||||
-rm -f "$@"
|
||||
$(LN_S) ../libaltos/.libs/"$@" .
|
||||
|
||||
libaltos_armel.so: build-libaltos
|
||||
-rm -f "$@"
|
||||
$(LN_S) ../libaltos/.libs/"$@" .
|
||||
|
||||
libaltos_armhf.so: build-libaltos
|
||||
-rm -f "$@"
|
||||
$(LN_S) ../libaltos/.libs/"$@" .
|
||||
|
||||
libaltos.dylib:
|
||||
-rm -f "$@"
|
||||
$(LN_S) ../libaltos/"$@" .
|
||||
|
||||
altos.dll: build-libaltos
|
||||
-rm -f "$@"
|
||||
$(LN_S) ../libaltos/"$@" .
|
||||
|
||||
altos64.dll: build-libaltos
|
||||
-rm -f "$@"
|
||||
$(LN_S) ../libaltos/"$@" .
|
||||
|
||||
build-libaltos:
|
||||
+cd ../libaltos && make
|
||||
|
||||
$(ALTOSLIB_CLASS):
|
||||
-rm -f "$@"
|
||||
$(LN_S) ../altoslib/"$@" .
|
||||
|
||||
$(ALTOSUILIB_CLASS):
|
||||
-rm -f "$@"
|
||||
$(LN_S) ../altosuilib/"$@" .
|
||||
|
||||
$(FREETTS_CLASS):
|
||||
-rm -f "$@"
|
||||
$(LN_S) "$(FREETTS)"/"$@" .
|
||||
|
||||
$(JFREECHART_CLASS):
|
||||
-rm -f "$@"
|
||||
$(LN_S) "$(JFREECHART)"/"$@" .
|
||||
|
||||
$(JCOMMON_CLASS):
|
||||
-rm -f "$@"
|
||||
$(LN_S) "$(JCOMMON)"/"$@" .
|
||||
|
||||
$(LINUX_DIST): $(LINUX_FILES) $(LINUX_EXTRA)
|
||||
-rm -f $@
|
||||
-rm -rf linux
|
||||
mkdir -p linux/AltOS
|
||||
cp -p $(LINUX_FILES) linux/AltOS
|
||||
cp -p altosui-fat linux/AltOS/altosui
|
||||
chmod +x linux/AltOS/altosui
|
||||
tar cjf $@ -C linux AltOS
|
||||
|
||||
$(LINUX_SH): $(LINUX_DIST) linux-install.sh
|
||||
cat linux-install.sh $(LINUX_DIST) > $@
|
||||
chmod +x $@
|
||||
|
||||
$(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) Makefile
|
||||
-rm -f $@
|
||||
-rm -rf macosx
|
||||
mkdir macosx
|
||||
cp -a AltosUI.app macosx/
|
||||
cp -a $(MACOSX_INSTALL) macosx
|
||||
cp -a ReadMe-Mac.rtf macosx/ReadMe-AltosUI.rtf
|
||||
mkdir -p macosx/Doc
|
||||
cp -a $(DOC) macosx/Doc
|
||||
cp -p Info.plist macosx/AltosUI.app/Contents
|
||||
mkdir -p macosx/AltOS-$(VERSION) macosx/AltosUI.app/Contents/Resources/Java
|
||||
cp -p $(MACOSX_ICONS) macosx/AltosUI.app/Contents/Resources
|
||||
cp -p $(FATJAR) macosx/AltosUI.app/Contents/Resources/Java/altosui.jar
|
||||
cp -p libaltos.dylib macosx/AltosUI.app/Contents/Resources/Java
|
||||
cp -p $(ALTOSLIB_CLASS) macosx/AltosUI.app/Contents/Resources/Java
|
||||
cp -p $(ALTOSUILIB_CLASS) macosx/AltosUI.app/Contents/Resources/Java
|
||||
cp -p $(FREETTS_CLASS) macosx/AltosUI.app/Contents/Resources/Java
|
||||
cp -p $(JFREECHART_CLASS) macosx/AltosUI.app/Contents/Resources/Java
|
||||
cp -p $(JCOMMON_CLASS) macosx/AltosUI.app/Contents/Resources/Java
|
||||
cp -p $(MACOSX_EXTRA) macosx/AltOS-$(VERSION)
|
||||
genisoimage -D -V AltOS-$(VERSION) -no-pad -r -apple -o $@ macosx
|
||||
|
||||
$(WINDOWS_DIST): $(WINDOWS_FILES) altos-windows.nsi Instdrv/NSIS/Includes/java.nsh
|
||||
-rm -f $@
|
||||
makensis -Oaltos-windows.log "-XOutFile $@" "-DVERSION=$(VERSION)" altos-windows.nsi || (cat altos-windows.log && exit 1)
|
||||
if [ "$(HAVE_WINDOWS_KEY)" = "yes" ]; then \
|
||||
jsign --keystore "$(WINDOWSKEYFILE)" --alias 1 \
|
||||
--storetype PKCS12 --storepass `cat "$(WINDOWSKEYPASSFILE)"` \
|
||||
--tsaurl http://ts.ssl.com --tsmode RFC3161 $@ ; \
|
||||
fi
|
59
altosui/ReadMe-Mac.rtf
Normal file
59
altosui/ReadMe-Mac.rtf
Normal file
@@ -0,0 +1,59 @@
|
||||
{\rtf1\ansi\deff3\adeflang1025
|
||||
{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}{\f4\froman\fprq2\fcharset0 Arial;}{\f5\froman\fprq2\fcharset0 Helvetica LT Std;}{\f6\froman\fprq2\fcharset0 Helvetica{\*\falt Arial};}{\f7\fnil\fprq2\fcharset0 SimSun;}{\f8\fnil\fprq2\fcharset0 Helvetica LT Std;}{\f9\fnil\fprq2\fcharset0 Helvetica{\*\falt Arial};}{\f10\fnil\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}}
|
||||
{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}
|
||||
{\stylesheet{\s0\snext0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af7\langfe1081\dbch\af10\afs24\alang1081\loch\f3\fs24\lang1033 Normal;}
|
||||
{\*\cs15\snext15 Numbering Symbols;}
|
||||
{\s16\sbasedon0\snext17\ql\nowidctlpar\hyphpar0\sb240\sa120\keepn\ltrpar\cf0\kerning1\dbch\af7\langfe1081\dbch\af10\afs24\loch\f4\fs28\lang1033 Heading;}
|
||||
{\s17\sbasedon0\snext17\sl276\slmult1\ql\nowidctlpar\hyphpar0\sb0\sa140\ltrpar\cf0\kerning1\dbch\af7\langfe1081\dbch\af10\afs24\loch\f3\fs24\lang1033 Text Body;}
|
||||
{\s18\sbasedon17\snext18\sl276\slmult1\ql\nowidctlpar\hyphpar0\sb0\sa120\ltrpar\cf0\kerning1\dbch\af7\langfe1081\dbch\af10\afs24\loch\f3\fs24\lang1033 List;}
|
||||
{\s19\sbasedon0\snext19\ql\nowidctlpar\hyphpar0\sb120\sa120\ltrpar\cf0\i\kerning1\dbch\af7\langfe1081\dbch\af10\afs24\loch\f3\fs24\lang1033 Caption;}
|
||||
{\s20\sbasedon0\snext20\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af7\langfe1081\dbch\af10\afs24\loch\f3\fs24\lang1033 Index;}
|
||||
{\s21\sbasedon0\snext21\ql\nowidctlpar\hyphpar0\sb0\sa120\ltrpar\cf0\kerning1\dbch\af7\langfe1081\dbch\af10\afs24\loch\f3\fs24\lang1033 Text body;}
|
||||
}{\*\listtable{\list\listtemplateid1
|
||||
{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'00);}{\levelnumbers\'01;}\fi-360\li720}
|
||||
{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'01.;}{\levelnumbers\'01;}\fi-360\li1080}
|
||||
{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'02.;}{\levelnumbers\'01;}\fi-360\li1440}
|
||||
{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'03.;}{\levelnumbers\'01;}\fi-360\li1800}
|
||||
{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'04.;}{\levelnumbers\'01;}\fi-360\li2160}
|
||||
{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'05.;}{\levelnumbers\'01;}\fi-360\li2520}
|
||||
{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'06.;}{\levelnumbers\'01;}\fi-360\li2880}
|
||||
{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'07.;}{\levelnumbers\'01;}\fi-360\li3240}
|
||||
{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'08.;}{\levelnumbers\'01;}\fi-360\li3600}\listid1}
|
||||
{\list\listtemplateid2
|
||||
{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}
|
||||
{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}
|
||||
{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}
|
||||
{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}
|
||||
{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}
|
||||
{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}
|
||||
{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}
|
||||
{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}
|
||||
{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}\listid2}
|
||||
}{\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}}{\*\generator LibreOffice/6.1.2.1$Linux_X86_64 LibreOffice_project/10$Build-1}{\info{\creatim\yr2013\mo1\dy6\hr13\min7}{\revtim\yr2018\mo10\dy5\hr19\min22}{\printim\yr0\mo0\dy0\hr0\min0}}{\*\userprops}\deftab709
|
||||
\hyphauto0\viewscale150
|
||||
{\*\pgdsctbl
|
||||
{\pgdsc0\pgdscuse451\pgwsxn12240\pghsxn15840\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\pgdscnxt0 Default Style;}}
|
||||
\formshade{\*\pgdscno0}\paperh15840\paperw12240\margl1134\margr1134\margt1134\margb1134\sectd\sbknone\sectunlocked1\pgndec\pgwsxn12240\pghsxn15840\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc
|
||||
{\*\ftnsep\chftnsep}\pgndec\pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af7\langfe1081\dbch\af10\afs24\alang1081\loch\f3\fs24\lang1033{\cf0\kerning1\dbch\af7\langfe1081\dbch\af8\rtlch \ltrch\loch\fs24\lang1033\loch\f5\hich\af5
|
||||
Installing AltOS software for Mac OS X Computers}
|
||||
\par \pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af7\langfe1081\dbch\af10\afs24\alang1081\loch\f3\fs24\lang1033\cf0\kerning1\dbch\af7\langfe1081\dbch\af9\rtlch \ltrch\loch\fs24\lang1033\loch\f6\hich\af6
|
||||
|
||||
\par \pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af7\langfe1081\dbch\af10\afs24\alang1081\loch\f3\fs24\lang1033{\cf0\kerning1\dbch\af7\langfe1081\dbch\af8\rtlch \ltrch\loch\fs24\lang1033\loch\f5\hich\af5
|
||||
The AltOS distribution for Mac OS X consists of:}
|
||||
\par \pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af7\langfe1081\dbch\af10\afs24\alang1081\loch\f3\fs24\lang1033\cf0\kerning1\dbch\af7\langfe1081\dbch\af8\rtlch \ltrch\loch\fs24\lang1033\loch\f5\hich\af5
|
||||
|
||||
\par \pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af7\langfe1081\dbch\af10\afs24\alang1081\loch\f3\fs24\lang1033{\listtext\pard\plain 1)\tab}\ilvl0\ls1 \li1440\ri0\lin1440\rin0\fi-360\li720\ri0\lin720\rin0\fi-360{\cf0\kerning1\dbch\af7\langfe1081\dbch\af8\rtlch \ltrch\loch\fs24\lang1033\loch\f5\hich\af5
|
||||
The AltosUI application}
|
||||
\par \pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af7\langfe1081\dbch\af10\afs24\alang1081\loch\f3\fs24\lang1033{\listtext\pard\plain 2)\tab}\ilvl0\ls1 \li1440\ri0\lin1440\rin0\fi-360\li720\ri0\lin720\rin0\fi-360{\cf0\kerning1\dbch\af7\langfe1081\dbch\af8\rtlch \ltrch\loch\fs24\lang1033\loch\f5\hich\af5
|
||||
Current AltOS firmware for Altus Metrum products}
|
||||
\par \pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af7\langfe1081\dbch\af10\afs24\alang1081\loch\f3\fs24\lang1033\cf0\kerning1\dbch\af7\langfe1081\dbch\af8\rtlch \ltrch\loch\fs24\lang1033\loch\f5\hich\af5
|
||||
|
||||
\par \pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af7\langfe1081\dbch\af10\afs24\alang1081\loch\f3\fs24\lang1033{\cf0\kerning1\dbch\af7\langfe1081\dbch\af8\rtlch \ltrch\loch\fs24\lang1033\loch\f5\hich\af5
|
||||
Install the AltosUI application by control-clicking the install-macosx script and selecting \u8220\'93Open\u8221\'94 from the menu. This will display a dialog asking if you are sure you want to open it. Select \u8220\'93Open\u8221\'94 from the dialog to execute the script. This will install the software, documentation and firmware in your home Applications/AltOS folder. You can move it afte}{\cf0\kerning1\dbch\af7\langfe1081\dbch\af8\rtlch \ltrch\loch\fs24\lang1033\loch\f5\hich\af5
|
||||
r}{\cf0\kerning1\dbch\af7\langfe1081\dbch\af8\rtlch \ltrch\loch\fs24\lang1033\loch\f5\hich\af5
|
||||
wards if you choose.}
|
||||
\par \pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af7\langfe1081\dbch\af10\afs24\alang1081\loch\f3\fs24\lang1033\cf0\kerning1\dbch\af7\langfe1081\dbch\af8\rtlch \ltrch\loch\fs24\lang1033\loch\f5\hich\af5
|
||||
|
||||
\par \pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af7\langfe1081\dbch\af10\afs24\alang1081\loch\f3\fs24\lang1033\sl240\slmult1\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640{\cf0\kerning1\dbch\af7\langfe1081\dbch\af9\rtlch \ltrch\loch\fs24\lang1033\loch\f6\hich\af6
|
||||
Thanks for choosing AltusMetrum products!}
|
||||
\par }
|
268
altosui/altos-windows.nsi.in
Normal file
268
altosui/altos-windows.nsi.in
Normal file
@@ -0,0 +1,268 @@
|
||||
!addplugindir Instdrv/NSIS/Plugins
|
||||
!addincludedir Instdrv/NSIS/Includes
|
||||
!include x64.nsh
|
||||
!include java.nsh
|
||||
!include refresh-sh.nsh
|
||||
|
||||
!define REG_NAME "Altus Metrum"
|
||||
!define PROG_ID_TELEM "altusmetrum.altosui.telem.1"
|
||||
!define PROG_ID_EEPROM "altusmetrum.altosui.eeprom.1"
|
||||
!define FAT_NAME "altosui-fat.jar"
|
||||
!define WIN_APP_ICON "altusmetrum-altosui.ico"
|
||||
!define WIN_APP_EXE "altusmetrum-altosui.exe"
|
||||
!define WIN_TELEM_EXE "application-vnd.altusmetrum.telemetry.exe"
|
||||
!define WIN_EEPROM_EXE "application-vnd.altusmetrum.eeprom.exe"
|
||||
|
||||
Name "${REG_NAME} Installer"
|
||||
|
||||
; Default install directory
|
||||
InstallDir "$PROGRAMFILES\AltusMetrum"
|
||||
|
||||
; Tell the installer where to re-install a new version
|
||||
InstallDirRegKey HKLM "Software\${REG_NAME}" "Install_Dir"
|
||||
|
||||
LicenseText "GNU General Public License Version 2"
|
||||
LicenseData "../COPYING"
|
||||
|
||||
; Need admin privs for Vista or Win7
|
||||
RequestExecutionLevel admin
|
||||
|
||||
ShowInstDetails Show
|
||||
|
||||
ComponentText "${REG_NAME} Software and Driver Installer"
|
||||
|
||||
Function .onInit
|
||||
DetailPrint "Checking host operating system"
|
||||
${If} ${RunningX64}
|
||||
DetailPrint "Installer running on 64-bit host"
|
||||
SetRegView 64
|
||||
StrCpy $INSTDIR "$PROGRAMFILES64\AltusMetrum"
|
||||
${DisableX64FSRedirection}
|
||||
${EndIf}
|
||||
FunctionEnd
|
||||
|
||||
Function un.onInit
|
||||
DetailPrint "Checking host operating system"
|
||||
${If} ${RunningX64}
|
||||
DetailPrint "Installer running on 64-bit host"
|
||||
SetRegView 64
|
||||
StrCpy $INSTDIR "$PROGRAMFILES64\AltusMetrum"
|
||||
${DisableX64FSRedirection}
|
||||
${EndIf}
|
||||
FunctionEnd
|
||||
|
||||
; Pages to present
|
||||
|
||||
Page license
|
||||
Page components
|
||||
Page directory
|
||||
Page instfiles
|
||||
|
||||
UninstPage uninstConfirm
|
||||
UninstPage instfiles
|
||||
|
||||
; And the stuff to install
|
||||
|
||||
Section "Install Driver" InstDriver
|
||||
|
||||
InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} AltusMetrumSerial
|
||||
Pop $0
|
||||
DetailPrint "InitDriverSetup: $0"
|
||||
InstDrv::DeleteOemInfFiles /NOUNLOAD
|
||||
InstDrv::CreateDevice /NOUNLOAD
|
||||
|
||||
SetOutPath $INSTDIR
|
||||
File "../altusmetrum.inf"
|
||||
File "../altusmetrum.cat"
|
||||
|
||||
${DisableX64FSRedirection}
|
||||
IfFileExists $WINDIR\System32\PnPutil.exe 0 nopnp
|
||||
${DisableX64FSRedirection}
|
||||
nsExec::ExecToLog '"$WINDIR\System32\PnPutil.exe" -i -a "$INSTDIR\altusmetrum.inf"'
|
||||
Goto done
|
||||
nopnp:
|
||||
InstDrv::InstallDriver /NOUNLOAD "$INSTDIR\altusmetrum.inf"
|
||||
done:
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "${REG_NAME} Application"
|
||||
Call DetectJRE
|
||||
|
||||
SetOutPath $INSTDIR
|
||||
|
||||
File "${FAT_NAME}"
|
||||
File "altoslib_@ALTOSLIB_VERSION@.jar"
|
||||
File "altosuilib_@ALTOSUILIB_VERSION@.jar"
|
||||
File "cmudict04.jar"
|
||||
File "cmulex.jar"
|
||||
File "cmu_time_awb.jar"
|
||||
File "cmutimelex.jar"
|
||||
File "cmu_us_kal.jar"
|
||||
File "en_us.jar"
|
||||
File "freetts.jar"
|
||||
File "jfreechart.jar"
|
||||
File "jcommon.jar"
|
||||
File "../icon/${WIN_APP_EXE}"
|
||||
|
||||
File "*.dll"
|
||||
|
||||
File "../icon/${WIN_APP_ICON}"
|
||||
|
||||
CreateShortCut "$SMPROGRAMS\${REG_NAME}.lnk" "$INSTDIR\${WIN_APP_EXE}" "" "$INSTDIR\${WIN_APP_ICON}"
|
||||
SectionEnd
|
||||
|
||||
Section "${REG_NAME} Desktop Shortcut"
|
||||
CreateShortCut "$DESKTOP\${REG_NAME}.lnk" "$INSTDIR\${WIN_APP_EXE}" "" "$INSTDIR\${WIN_APP_ICON}"
|
||||
SectionEnd
|
||||
|
||||
Section "Firmware"
|
||||
|
||||
SetOutPath $INSTDIR
|
||||
|
||||
File "../src/telemetrum-v2.0/telemetrum-v2.0-${VERSION}.ihx"
|
||||
File "../src/telemetrum-v3.0/telemetrum-v3.0-${VERSION}.ihx"
|
||||
File "../src/telemetrum-v4.0/telemetrum-v4.0-${VERSION}.ihx"
|
||||
File "../src/telemini-v3.0/telemini-v3.0-${VERSION}.ihx"
|
||||
File "../src/telegps-v1.0/telegps-v1.0-${VERSION}.ihx"
|
||||
File "../src/telegps-v2.0/telegps-v2.0-${VERSION}.ihx"
|
||||
File "../src/telegps-v3.0/telegps-v3.0-${VERSION}.ihx"
|
||||
File "../src/teledongle-v3.0/teledongle-v3.0-${VERSION}.ihx"
|
||||
File "../src/telebt-v3.0/telebt-v3.0-${VERSION}.ihx"
|
||||
File "../src/telebt-v4.0/telebt-v4.0-${VERSION}.ihx"
|
||||
File "../src/telemega-v1.0/telemega-v1.0-${VERSION}.ihx"
|
||||
File "../src/telemega-v2.0/telemega-v2.0-${VERSION}.ihx"
|
||||
File "../src/telemega-v3.0/telemega-v3.0-${VERSION}.ihx"
|
||||
File "../src/telemega-v4.0/telemega-v4.0-${VERSION}.ihx"
|
||||
File "../src/telemega-v5.0/telemega-v5.0-${VERSION}.ihx"
|
||||
File "../src/telemega-v6.0/telemega-v6.0-${VERSION}.ihx"
|
||||
File "../src/easymini-v1.0/easymini-v1.0-${VERSION}.ihx"
|
||||
File "../src/easymini-v2.0/easymini-v2.0-${VERSION}.ihx"
|
||||
File "../src/easymini-v3.0/easymini-v3.0-${VERSION}.ihx"
|
||||
File "../src/easymega-v1.0/easymega-v1.0-${VERSION}.ihx"
|
||||
File "../src/easymega-v2.0/easymega-v2.0-${VERSION}.ihx"
|
||||
File "../src/easymotor-v3/easymotor-v3-${VERSION}.ihx"
|
||||
File "../src/easytimer-v1/easytimer-v1-${VERSION}.ihx"
|
||||
File "../src/easytimer-v2/easytimer-v2-${VERSION}.ihx"
|
||||
File "../src/telelco-v2.0/telelco-v2.0-${VERSION}.ihx"
|
||||
File "../src/telefireeight-v1.0/telefireeight-v1.0-${VERSION}.ihx"
|
||||
File "../src/telefireeight-v2.0/telefireeight-v2.0-${VERSION}.ihx"
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Documentation"
|
||||
|
||||
SetOutPath $INSTDIR
|
||||
|
||||
File "../doc/altusmetrum.pdf"
|
||||
File "../doc/altos.pdf"
|
||||
File "../doc/telemetry.pdf"
|
||||
File "../doc/motortest.pdf"
|
||||
File "../doc/telemetrum-outline.pdf"
|
||||
File "../doc/telemega-outline.pdf"
|
||||
File "../doc/easymini-outline.pdf"
|
||||
File "../doc/telemini-v1-outline.pdf"
|
||||
File "../doc/telemini-v3-outline.pdf"
|
||||
SectionEnd
|
||||
|
||||
Section "File Associations"
|
||||
|
||||
${DisableX64FSRedirection}
|
||||
|
||||
SetOutPath $INSTDIR
|
||||
|
||||
File "../icon/${WIN_TELEM_EXE}"
|
||||
File "../icon/${WIN_EEPROM_EXE}"
|
||||
|
||||
DeleteRegKey HKCR "${PROG_ID_TELEM}"
|
||||
DeleteRegKey HKCR "${PROG_ID_EEPROM}"
|
||||
|
||||
DeleteRegKey HKCR ".eeprom\${PROG_ID_EEPROM}"
|
||||
DeleteRegValue HKCR ".eeprom\OpenWithProgids" "${PROG_ID_EEPROM}"
|
||||
DeleteRegKey HKCR ".telem\${PROG_ID_EEPROM}"
|
||||
DeleteRegValue HKCR ".telem\OpenWithProgids" "${PROG_ID_EEPROM}"
|
||||
|
||||
; .eeprom elements
|
||||
|
||||
WriteRegStr HKCR "${PROG_ID_EEPROM}" "" "Altus Metrum Log File"
|
||||
WriteRegStr HKCR "${PROG_ID_EEPROM}" "FriendlyTypeName" "Altus Metrum Log File"
|
||||
WriteRegStr HKCR "${PROG_ID_EEPROM}\CurVer" "" "${PROG_ID_EEPROM}"
|
||||
WriteRegStr HKCR "${PROG_ID_EEPROM}\DefaultIcon" "" '"$INSTDIR\${WIN_EEPROM_EXE}",-101'
|
||||
WriteRegExpandStr HKCR "${PROG_ID_EEPROM}\shell\open\command" "" '"$INSTDIR\${WIN_APP_EXE}" "%1"'
|
||||
|
||||
WriteRegStr HKCR ".eeprom" "" "${PROG_ID_EEPROM}"
|
||||
WriteRegStr HKCR ".eeprom" "PerceivedType" "Altus Metrum Log File"
|
||||
WriteRegStr HKCR ".eeprom" "Content Type" "application/vnd.altusmetrum.eeprom"
|
||||
|
||||
WriteRegStr HKCR ".eeprom\OpenWithProgids" "${PROG_ID_EEPROM}" ""
|
||||
WriteRegStr HKCR ".eeprom\${PROG_ID_EEPROM}" "" "${REG_NAME}"
|
||||
|
||||
; .telem elements
|
||||
|
||||
WriteRegStr HKCR "${PROG_ID_TELEM}" "" "Altus Metrum Telemetry File"
|
||||
WriteRegStr HKCR "${PROG_ID_TELEM}" "FriendlyTypeName" "Altus Metrum Telemetry File"
|
||||
WriteRegStr HKCR "${PROG_ID_TELEM}\CurVer" "" "${PROG_ID_TELEM}"
|
||||
WriteRegStr HKCR "${PROG_ID_TELEM}\DefaultIcon" "" '"$INSTDIR\${WIN_TELEM_EXE}",-101'
|
||||
WriteRegExpandStr HKCR "${PROG_ID_TELEM}\shell\open\command" "" '"$INSTDIR\${WIN_APP_EXE}" "%1"'
|
||||
|
||||
WriteRegStr HKCR ".telem" "" "${PROG_ID_TELEM}"
|
||||
WriteRegStr HKCR ".telem" "PerceivedType" "Altus Metrum Telemetry File"
|
||||
WriteRegStr HKCR ".telem" "Content Type" "application/vnd.altusmetrum.telemetry"
|
||||
|
||||
WriteRegStr HKCR ".telem\OpenWithProgids" "${PROG_ID_TELEM}" ""
|
||||
WriteRegStr HKCR ".telem\${PROG_ID_TELEM}" "" "${REG_NAME}"
|
||||
|
||||
Call RefreshShellIcons
|
||||
SectionEnd
|
||||
|
||||
Section "Uninstaller"
|
||||
|
||||
; Deal with the uninstaller
|
||||
|
||||
${DisableX64FSRedirection}
|
||||
SetOutPath $INSTDIR
|
||||
|
||||
; Write the install path to the registry
|
||||
WriteRegStr HKLM "SOFTWARE\${REG_NAME}" "Install_Dir" "$INSTDIR"
|
||||
|
||||
; Write the uninstall keys for windows
|
||||
WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "DisplayName" "${REG_NAME}"
|
||||
WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "UninstallString" '"$INSTDIR\uninstall-${REG_NAME}.exe"'
|
||||
WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "NoModify" "1"
|
||||
WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "NoRepair" "1"
|
||||
|
||||
WriteUninstaller "uninstall-${REG_NAME}.exe"
|
||||
SectionEnd
|
||||
|
||||
Section "Uninstall"
|
||||
|
||||
${DisableX64FSRedirection}
|
||||
|
||||
DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}"
|
||||
DeleteRegKey HKLM "SOFTWARE\${REG_NAME}"
|
||||
|
||||
DetailPrint "Delete uninstall reg entries"
|
||||
|
||||
DeleteRegKey HKCR "${PROG_ID_EEPROM}"
|
||||
DeleteRegKey HKCR "${PROG_ID_TELEM}"
|
||||
|
||||
DeleteRegKey HKCR ".eeprom\${PROG_ID_EEPROM}"
|
||||
DeleteRegValue HKCR ".eeprom\OpenWithProgids" "${PROG_ID_EEPROM}"
|
||||
|
||||
DeleteRegKey HKCR ".telem\${PROG_ID_TELEM}"
|
||||
DeleteRegValue HKCR ".telem\OpenWithProgids" "${PROG_ID_TELEM}"
|
||||
|
||||
DetailPrint "Delete file association reg entries"
|
||||
|
||||
Delete "$INSTDIR\${FAT_NAME}"
|
||||
Delete "$INSTDIR\uninstall-${REG_NAME}.exe"
|
||||
|
||||
Delete "$INSTDIR\${WIN_APP_ICON}"
|
||||
Delete "$INSTDIR\${WIN_APP_EXE}"
|
||||
|
||||
; Remove shortcuts, if any
|
||||
Delete "$SMPROGRAMS\${REG_NAME}.lnk"
|
||||
Delete "$DESKTOP\${REG_NAME}.lnk"
|
||||
|
||||
Call un.RefreshShellIcons
|
||||
SectionEnd
|
4
altosui/altosui-fat
Executable file
4
altosui/altosui-fat
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
me=`which "$0"`
|
||||
dir=`dirname "$me"`
|
||||
exec java -cp "$dir/*" -Djava.library.path="$dir" -jar "$dir"/altosui-fat.jar "$@"
|
46
altosui/altosui.1
Normal file
46
altosui/altosui.1
Normal file
@@ -0,0 +1,46 @@
|
||||
.\"
|
||||
.\" Copyright © 2010 Bdale Garbee <bdale@gag.com>
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\"
|
||||
.TH ALTOSUI 1 "altosui" ""
|
||||
.SH NAME
|
||||
altosui \- Rocket flight monitor
|
||||
.SH SYNOPSIS
|
||||
.B "altosui"
|
||||
.SH DESCRIPTION
|
||||
.I altosui
|
||||
connects to a TeleDongle or TeleMetrum device through a USB serial device.
|
||||
It provides a menu-oriented
|
||||
user interface to monitor, record and review rocket flight data.
|
||||
.SH USAGE
|
||||
When connected to a TeleDongle device, altosui turns on the radio
|
||||
receiver and listens for telemetry packets. It displays the received
|
||||
telemetry data, and reports flight status via voice synthesis. All
|
||||
received telemetry information is recorded to a file.
|
||||
.P
|
||||
When connected to a TeleMetrum device, altosui can be used to configure the
|
||||
TeleMetrum, and to downloads the eeprom data and store it in a file.
|
||||
.P
|
||||
A number of other menu options exist, including the ability to export flight
|
||||
data in different formats.
|
||||
.SH FILES
|
||||
All data log files are recorded into a user-specified directory
|
||||
(default ~/TeleMetrum). Files are named using the current date, the serial
|
||||
number of the reporting device, the flight number recorded in the data
|
||||
and either '.telem' for telemetry data or '.eeprom' for eeprom data.
|
||||
.SH AUTHOR
|
||||
Keith Packard
|
12
altosui/altusmetrum-altosui.desktop.in
Normal file
12
altosui/altusmetrum-altosui.desktop.in
Normal file
@@ -0,0 +1,12 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Version=1.0
|
||||
Name=AltOS UI
|
||||
GenericName=Altus Metrum Ground Station
|
||||
Comment=View and log downlink data from Altus Metrum products
|
||||
Icon=%icondir%/altusmetrum-altosui.svg
|
||||
Exec=%bindir%/altosui %F
|
||||
Terminal=false
|
||||
MimeType=application/vnd.altusmetrum.telemetry;application/vnd.altusmetrum.eeprom
|
||||
Categories=Education;Electronics;Science;
|
||||
Keywords=Rocket;Telemetry;GPS
|
BIN
altosui/altusmetrum.jpg
Normal file
BIN
altosui/altusmetrum.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 71 KiB |
2
altosui/ask-pass
Executable file
2
altosui/ask-pass
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
osascript -e 'display dialog "Password:" with hidden answer default answer "" with title "Password for '$USER'"' -e 'text returned of result'
|
55
altosui/install-macosx
Executable file
55
altosui/install-macosx
Executable file
@@ -0,0 +1,55 @@
|
||||
#!/bin/bash
|
||||
|
||||
JVM=/Library/Java/JavaVirtualMachines
|
||||
dir=`dirname "$0"`
|
||||
|
||||
case `id -u` in
|
||||
0)
|
||||
;;
|
||||
*)
|
||||
SUDO_ASKPASS="${dir}/ask-pass" sudo -A "$0" "$@"
|
||||
case $? in
|
||||
0)
|
||||
;;
|
||||
*)
|
||||
osascript -e 'display dialog "Installation failed. Incorrect password?" buttons {"OK"} default button 1 with title "Installation Status"' > /dev/null
|
||||
;;
|
||||
esac
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check for java
|
||||
if ls "$JVM" | grep -q temurin; then
|
||||
echo "Adoptium already present"
|
||||
else
|
||||
open https://adoptium.net/
|
||||
osascript -e 'display dialog "Install Java from https://adoptium.net then click Continue" buttons {"Continue"} default button 1 with title "Install Java"' >/dev/null
|
||||
fi
|
||||
|
||||
cd "$dir"
|
||||
LIBRARY=/Library/AltusMetrum
|
||||
APPLICATIONS=/Applications
|
||||
INSTALLED=
|
||||
for file in *; do
|
||||
echo 'Installing' "$file"
|
||||
case "$file" in
|
||||
*.app)
|
||||
mkdir -p "${APPLICATIONS}"
|
||||
if [ -d "${APPLICATIONS}/${file}" ]; then
|
||||
rm -rf "${APPLICATIONS}/${file}"
|
||||
fi
|
||||
cp -a "$file" "${APPLICATIONS}/${file}"
|
||||
chmod -R +w "${APPLICATIONS}/${file}"
|
||||
xattr -rc "${APPLICATIONS}/${file}"
|
||||
APP=`basename "$file" .app`
|
||||
INSTALLED="${INSTALLED} ${APP}"
|
||||
;;
|
||||
*)
|
||||
mkdir -p "${LIBRARY}"
|
||||
cp -a "$file" "${LIBRARY}"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
open "${LIBRARY}"
|
||||
osascript -e 'display dialog "Installation of'"${INSTALLED}"' complete" with title "Installation Complete" buttons {"OK"} default button 1' >/dev/null
|
244
altosui/linux-install.sh
Normal file
244
altosui/linux-install.sh
Normal file
@@ -0,0 +1,244 @@
|
||||
#!/bin/sh
|
||||
|
||||
can_ask=y
|
||||
|
||||
finish()
|
||||
{
|
||||
if [ "$can_ask" = "y" ]; then
|
||||
echo ""
|
||||
echo -n "Press enter to continue..."
|
||||
read foo
|
||||
fi
|
||||
exit $1
|
||||
}
|
||||
|
||||
#
|
||||
# Make sure we have a terminal to talk to
|
||||
#
|
||||
|
||||
if tty -s; then
|
||||
:
|
||||
else
|
||||
case "$DISPLAY" in
|
||||
"")
|
||||
echo 'No user input available'
|
||||
can_ask=n
|
||||
;;
|
||||
*)
|
||||
GUESS_XTERMS="x-terminal-emulator xterm rxvt roxterm gnome-terminal dtterm eterm Eterm kvt konsole aterm"
|
||||
for a in $GUESS_XTERMS; do
|
||||
if type $a >/dev/null 2>&1; then
|
||||
XTERM=$a
|
||||
break
|
||||
fi
|
||||
done
|
||||
case "$XTERM" in
|
||||
"")
|
||||
echo 'No terminal emulator available'
|
||||
can_ask=n
|
||||
;;
|
||||
*)
|
||||
exec "$XTERM" -e "sh '$0'"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
#
|
||||
# Make sure we can run java
|
||||
#
|
||||
|
||||
echo -n "Checking for java..."
|
||||
|
||||
if java -version > /dev/null 2>&1; then
|
||||
echo " found it."
|
||||
else
|
||||
echo " java isn't working."
|
||||
echo ""
|
||||
echo "You'll need to install a java runtime system"
|
||||
echo "on this computer before AltOS will work properly."
|
||||
finish 1
|
||||
fi
|
||||
|
||||
#
|
||||
# Pick an installation target
|
||||
#
|
||||
|
||||
if [ '(' -d /opt -a -w /opt ')' -o '(' -d /opt/AltOS -a -w /opt/AltOS ')' ]; then
|
||||
target_default=/opt
|
||||
else
|
||||
target_default="$HOME"
|
||||
fi
|
||||
|
||||
case "$#" in
|
||||
0)
|
||||
echo -n "Installation location [default: $target_default] "
|
||||
if [ "$can_ask" = "y" ]; then
|
||||
read target
|
||||
else
|
||||
echo ""
|
||||
target=""
|
||||
fi
|
||||
case "$target" in
|
||||
"")
|
||||
target="$target_default"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
target="$1"
|
||||
;;
|
||||
esac
|
||||
|
||||
target_altos="$target"/AltOS
|
||||
|
||||
echo -n "Installing to $target..."
|
||||
|
||||
#
|
||||
# Make sure the target exists
|
||||
#
|
||||
mkdir -p "$target_altos"
|
||||
|
||||
if [ ! -d "$target_altos" ]; then
|
||||
echo "$target_altos does not exist and cannot be created"
|
||||
finish 1
|
||||
fi
|
||||
|
||||
if [ ! -w "$target_altos" ]; then
|
||||
echo "$target_altos cannot be written"
|
||||
finish 1
|
||||
fi
|
||||
|
||||
#
|
||||
# Unpack the tar archive appended to the end of this script
|
||||
#
|
||||
archive_line=`awk '/^__ARCHIVE_BELOW__/ {print NR + 1; exit 0; }' "$0"`
|
||||
|
||||
tail -n+$archive_line "$0" | tar xjf - -C "$target"
|
||||
|
||||
case $? in
|
||||
0)
|
||||
echo " done."
|
||||
;;
|
||||
*)
|
||||
echo "Install failed."
|
||||
finish 1
|
||||
;;
|
||||
esac
|
||||
|
||||
#
|
||||
# Create the .desktop file by editing the paths
|
||||
#
|
||||
|
||||
case "$target" in
|
||||
/*)
|
||||
target_abs="$target"
|
||||
;;
|
||||
*)
|
||||
target_abs=`pwd`/$target
|
||||
;;
|
||||
esac
|
||||
|
||||
BIN="$target_abs"/AltOS
|
||||
|
||||
for infile in "$target"/AltOS/*.desktop.in; do
|
||||
desktop="$target"/AltOS/`basename "$infile" .in`
|
||||
rm -f "$desktop"
|
||||
sed -e "s;%bindir%;$BIN;" -e "s;%icondir%;$BIN;" "$infile" > "$desktop"
|
||||
chmod +x "$desktop"
|
||||
done
|
||||
|
||||
#
|
||||
# Install the .desktop file
|
||||
#
|
||||
|
||||
for desktop in "$target"/AltOS/*.desktop; do
|
||||
case `id -u` in
|
||||
0)
|
||||
xdg-desktop-menu install --mode system "$desktop"
|
||||
;;
|
||||
*)
|
||||
xdg-desktop-menu install --mode user "$desktop"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
#
|
||||
# Install mime type file
|
||||
#
|
||||
|
||||
for mimetype in "$target"/AltOS/*-mimetypes.xml; do
|
||||
case `id -u` in
|
||||
0)
|
||||
xdg-mime install --mode system "$mimetype"
|
||||
;;
|
||||
*)
|
||||
xdg-mime install --mode user "$mimetype"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
#
|
||||
# Install icons
|
||||
#
|
||||
|
||||
for icon_dir in /usr/share/icons/hicolor/scalable/mimetypes "$HOME/.icons" "$HOME/.kde/share/icons"; do
|
||||
if [ -w "$icon_dir" ]; then
|
||||
cp "$target"/AltOS/*.svg "$icon_dir"
|
||||
update-icon-caches "$icon_dir"
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
#
|
||||
# Install icon to desktop if desired
|
||||
#
|
||||
|
||||
if [ -d $HOME/Desktop ]; then
|
||||
default_desktop=n
|
||||
if [ "$can_ask" = "y" ]; then
|
||||
:
|
||||
else
|
||||
default_desktop=y
|
||||
fi
|
||||
|
||||
answered=n
|
||||
while [ "$answered" = "n" ]; do
|
||||
echo -n "Install icons to desktop? [default: $default_desktop] "
|
||||
if [ "$can_ask" = "y" ]; then
|
||||
read do_desktop
|
||||
else
|
||||
echo
|
||||
do_desktop=""
|
||||
fi
|
||||
|
||||
case "$do_desktop" in
|
||||
"")
|
||||
do_desktop=$default_desktop
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$do_desktop" in
|
||||
[yYnN]*)
|
||||
answered=y
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
case "$do_desktop" in
|
||||
[yY]*)
|
||||
echo -n "Installing desktop icons..."
|
||||
for d in "$target"/AltOS/*.desktop; do
|
||||
base=`basename $d`
|
||||
cp --remove-destination "$d" "$HOME/Desktop/"
|
||||
done
|
||||
;;
|
||||
esac
|
||||
|
||||
echo " done."
|
||||
fi
|
||||
|
||||
finish 0
|
||||
|
||||
__ARCHIVE_BELOW__
|
7
altosui/mdwn.tmpl
Normal file
7
altosui/mdwn.tmpl
Normal file
@@ -0,0 +1,7 @@
|
||||
[[!inline pages="./%version%/release-notes-%version%.html" rss="no" raw="yes" ]]
|
||||
|
||||
- Available Files:
|
||||
- [Windows Installer](/AltOS/releases/%version%/Altos-Windows-%version_dash%.exe)
|
||||
- [Mac OS X Package](/AltOS/releases/%version%/Altos-Mac-%version%.dmg)
|
||||
- [Linux](/AltOS/releases/%version%/Altos-Linux-%version%.sh)
|
||||
- [Source Snapshot](http://git.gag.com/?p=fw/altos;a=snapshot;h=refs/tags/%version%;sf=tgz)
|
Reference in New Issue
Block a user