Initial Commit - Copy from Altus Metrum AltOS

This commit is contained in:
2024-06-25 19:03:04 +02:00
commit 13fc49c923
2048 changed files with 1206748 additions and 0 deletions

22
micropeak/.gitignore vendored Normal file
View File

@@ -0,0 +1,22 @@
*.jar
Manifest.txt
Manifest-fat.txt
classes
*.stamp
micropeak
micropeak-test
micropeak-jdb
micropeak-windows.log
micropeak-windows.nsi
MicroPeak-Linux-*
MicroPeak-Mac-*
MicroPeak-Windows-*
*.desktop
*.dll
*.dylib
*.so
linux
macosx
CDM*.exe
FTDI*.dmg
Info.plist

65
micropeak/Info.plist.in Normal file
View File

@@ -0,0 +1,65 @@
<?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>MicroPeak</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.micropeak</string>
<key>CFBundleSignature</key>
<string>Altu</string>
<key>CFBundleGetInfoString</key>
<string>MicroPeak UI version @VERSION@</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleIconFile</key>
<string>altusmetrum-micropeak.icns</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>MicroPeak data file</string>
<key>CFBundleTypeIconFile</key>
<string>application-vnd.altusmetrum.micropeak.icns</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>mpd</string>
</array>
<key>CFBundleTypeRole</key>
<string>Editor</string>
</dict>
</array>
<key>Java</key>
<dict>
<key>MainClass</key>
<string>org.altusmetrum.micropeak.MicroPeak</string>
<key>JVMVersion</key>
<string>1.5+</string>
<key>ClassPath</key>
<array>
<string>$JAVAROOT/micropeak.jar</string>
</array>
<key>Properties</key>
<dict>
<key>apple.laf.useScreenMenuBar</key>
<string>true</string>
</dict>
<key>VMOptions</key>
<array>
<string>-Xms512M</string>
<string>-Xmx512M</string>
<string>-Dosgi.clean=true</string>
</array>
</dict>
</dict>
</plist>

372
micropeak/Makefile.am Normal file
View File

@@ -0,0 +1,372 @@
# location of code signing key, et al
JAVAROOT=classes
AM_JAVACFLAGS=$(JAVAC_VERSION_FLAGS) -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked
man_MANS=micropeak.1
altoslibdir=$(libdir)/altos
CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../altoslib/*:../altosuilib/*:../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar"
bin_SCRIPTS=micropeak
micropeakdir=$(datadir)/java
micropeak_JAVA= \
MicroPeak.java \
MicroData.java \
MicroDownload.java \
MicroExport.java \
MicroFile.java \
MicroFrame.java \
MicroRaw.java \
MicroSave.java \
MicroSerial.java \
MicroSerialLog.java \
MicroFileChooser.java \
MicroDeviceDialog.java \
MicroUSB.java
JFREECHART_CLASS= \
jfreechart.jar
JCOMMON_CLASS=\
jcommon.jar
JAR=micropeak.jar
FATJAR=micropeak-fat.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 \
altos64.dll \
altos.dll
ALTOSLIB_CLASS=\
altoslib_$(ALTOSLIB_VERSION).jar
ALTOSUILIB_CLASS=\
altosuilib_$(ALTOSUILIB_VERSION).jar
# Icons
ICONDIR=$(top_srcdir)/icon
JAVA_ICONS=\
$(ICONDIR)/altusmetrum-micropeak-16.png \
$(ICONDIR)/altusmetrum-micropeak-32.png \
$(ICONDIR)/altusmetrum-micropeak-48.png \
$(ICONDIR)/altusmetrum-micropeak-64.png \
$(ICONDIR)/altusmetrum-micropeak-128.png\
$(ICONDIR)/altusmetrum-micropeak-256.png
# icon base names for jar
ICONJAR= \
-C $(ICONDIR) altusmetrum-micropeak-16.png \
-C $(ICONDIR) altusmetrum-micropeak-32.png \
-C $(ICONDIR) altusmetrum-micropeak-48.png \
-C $(ICONDIR) altusmetrum-micropeak-64.png \
-C $(ICONDIR) altusmetrum-micropeak-128.png\
-C $(ICONDIR) altusmetrum-micropeak-256.png
WINDOWS_ICONS =\
../icon/altusmetrum-micropeak.ico \
../icon/altusmetrum-micropeak.exe
../icon/application-vnd.altusmetrum.micropeak.ico \
../icon/application-vnd.altusmetrum.micropeak.ico
MACOSX_ICONS =\
../icon/altusmetrum-micropeak.icns \
../icon/application-vnd.altusmetrum.micropeak.icns
LINUX_ICONS =\
$(ICONDIR)/altusmetrum-micropeak.svg \
$(ICONDIR)/application-vnd.altusmetrum.micropeak.svg
LINUX_MIMETYPE =\
$(ICONDIR)/org-altusmetrum-mimetypes.xml
FIRMWARE_MP_0_1=$(top_srcdir)/src/micropeak/micropeak-v0.1-$(VERSION).ihx
FIRMWARE_MP=$(FIRMWARE_MP_0_1)
FIRMWARE_MS_1_0=$(top_srcdir)/src/microsplash/microsplash-v1.0-$(VERSION).ihx
FIRMWARE_MS=$(FIRMWARE_MS_1_0)
FIRMWARE=$(FIRMWARE_MP) $(FIRMWARE_MS)
desktopdir = $(datadir)/applications
desktop_file = altusmetrum-micropeak.desktop
desktop_SCRIPTS = $(desktop_file)
all-local: micropeak-test micropeak-jdb $(JAR) $(MDWN)
clean-local:
-rm -rf classes $(JAR) $(FATJAR) \
MicroPeak-Linux-*.tar.bz2 MicroPeak-Mac-*.dmg MicroPeak-Windows-*.exe \
altoslib_*.jar altosuilib_*.jar \
$(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt \
micropeak micropeak-test micropeak-jdb macosx linux windows micropeak-windows.log \
micropeak-windows.nsi *.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 $@
LINUX_DIST=MicroPeak-Linux-$(VERSION).tar.bz2
LINUX_SH=MicroPeak-Linux-$(VERSION).sh
MACOSX_DIST=MicroPeak-Mac-$(VERSION).dmg
WINDOWS_DIST=MicroPeak-Windows-$(VERSION_DASH).exe
MDWN=$(VERSION).mdwn
MDWNTMPL=mdwn.tmpl
MICROPEAK_DOC=$(top_srcdir)/doc/micropeak.pdf
DOC=$(MICROPEAK_DOC)
FAT_FILES=$(FATJAR) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS)
LINUX_FILES=$(FAT_FILES) $(LIBALTOS_LINUX) $(FIRMWARE) $(DOC) $(desktop_file).in $(LINUX_ICONS) $(LINUX_MIMETYPE)
LINUX_EXTRA=micropeak-fat $(desktop_file).in
MACOSX_DRIVER_0_URL=http://www.ftdichip.com/Drivers/VCP/MacOSX/FTDIUSBSerialDriver_v2_2_18.dmg
MACOSX_DRIVER_0=FTDI_v2_2_18.dmg
MACOSX_DRIVER_1_URL=http://www.ftdichip.com/Drivers/VCP/MacOSX/FTDIUSBSerialDriver_v2_3.dmg
MACOSX_DRIVER_1=FTDI_v2_3.dmg
MACOSX_DRIVERS=$(MACOSX_DRIVER_1) $(MACOSX_DRIVER_0)
MACOSX_INFO_PLIST=Info.plist
MACOSX_README=ReadMe-Mac.rtf
MACOSX_INSTALL=../altosui/install-macosx ../altosui/ask-pass
MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(MACOSX_DRIVERS) $(MACOSX_README) $(DOC) $(MACOSX_ICONS) $(MACOSX_INSTALL)
MACOSX_EXTRA=$(FIRMWARE)
$(MACOSX_DRIVER_0):
wget -O $@ $(MACOSX_DRIVER_0_URL)
$(MACOSX_DRIVER_1):
wget -O $@ $(MACOSX_DRIVER_1_URL)
WINDOWS_DRIVER_URL=http://www.ftdichip.com/Drivers/CDM/CDM%20v2.12.00%20WHQL%20Certified.exe
WINDOWS_DRIVER=CDM_v2.12.00_WHQL_Certified.exe
$(WINDOWS_DRIVER):
wget -O "$(WINDOWS_DRIVER)" "$(WINDOWS_DRIVER_URL)"
WINDOWS_FILES=$(FAT_FILES) $(FIRMWARE) altos.dll altos64.dll $(DOC) $(WINDOWS_ICONS) $(WINDOWS_DRIVER)
if FATINSTALL
FATTARGET=$(FATDIR)/MicroPeak/releases/$(VERSION)
LINUX_SH_TARGET=$(FATTARGET)/$(LINUX_SH)
MACOSX_DIST_TARGET=$(FATTARGET)/$(MACOSX_DIST)
WINDOWS_DIST_TARGET=$(FATTARGET)/$(WINDOWS_DIST)
MDWN_TARGET=$(FATDIR)/MicroPeak/releases/$(MDWN)
RELNOTES=release-notes-$(VERSION).html
RELNOTES_SRC=$(top_builddir)/doc/$(RELNOTES)
RELNOTES_TARGET=$(FATTARGET)/$(RELNOTES)
fat-install: $(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)
micropeak: Makefile
echo "#!/bin/sh" > $@
echo 'exec java -Djava.library.path="$(altoslibdir)" -jar "$(micropeakdir)/micropeak.jar" "$$@"' >> $@
chmod +x $@
micropeak-jdb: Makefile
echo "#!/bin/sh" > $@
echo 'exec jdb -classpath "classes:./*:../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="../libaltos/.libs" org.altusmetrum.micropeak.MicroPeak "$$@"' >> $@
chmod +x $@
micropeak-test: Makefile
echo "#!/bin/sh" > $@
echo 'exec java -cp "./*:../libaltos/*:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="../libaltos/.libs" -jar micropeak.jar "$$@"' >> $@
chmod +x $@
install-micropeakJAVA: micropeak.jar
@$(NORMAL_INSTALL)
test -z "$(micropeakdir)" || $(MKDIR_P) "$(DESTDIR)$(micropeakdir)"
echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(micropeakdir)/micropeak.jar'"; \
$(INSTALL_DATA) "$<" "$(DESTDIR)$(micropeakdir)"
$(JAR): classmicropeak.stamp Manifest.txt $(JAVA_ICONS) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS)
jar cfm $@ Manifest.txt \
$(ICONJAR) \
-C classes org \
-C ../libaltos libaltosJNI
if STRIP_NONDETERMINISM
$(STRIP_NONDETERMINISM) $@
endif
$(FATJAR): classmicropeak.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(JAVA_ICONS)
jar cfm $@ Manifest-fat.txt \
$(ICONJAR) \
-C classes org \
-C ../libaltos libaltosJNI
if STRIP_NONDETERMINISM
$(STRIP_NONDETERMINISM) $@
endif
classaltosui.stamp: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS)
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: ../libaltos/altos.dll
-rm -f "$@"
$(LN_S) ../libaltos/"$@" .
altos64.dll: ../libaltos/altos64.dll
-rm -f "$@"
$(LN_S) ../libaltos/"$@" .
../libaltos/.libs/libaltos64.so: ../libaltos/.libs/libaltos32.so
../libaltos/.libs/libaltos32.so: build-libaltos
../libaltos/.libs/libaltos.so: build-libaltos
../libaltos/altos.dll: build-altos-dll
../libaltos/altos64.dll: build-altos64-dll
build-libaltos:
+cd ../libaltos && make libaltos.la
build-altos-dll:
+cd ../libaltos && make altos.dll
build-altos64-dll:
+cd ../libaltos && make altos64.dll
$(ALTOSLIB_CLASS):
-rm -f "$@"
$(LN_S) ../altoslib/"$@" .
$(ALTOSUILIB_CLASS):
-rm -f "$@"
$(LN_S) ../altosuilib/"$@" .
$(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/MicroPeak
cp -p $(LINUX_FILES) linux/MicroPeak
cp -p micropeak-fat linux/MicroPeak/micropeak
chmod +x linux/MicroPeak/micropeak
tar cjf $@ -C linux MicroPeak
$(LINUX_SH): $(LINUX_DIST) $(srcdir)/../altosui/linux-install.sh
sed 's/AltOS/MicroPeak/g' $(srcdir)/../altosui/linux-install.sh | cat - $(LINUX_DIST) > $@
chmod +x $@
$(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) Makefile
-rm -f $@
-rm -rf macosx
mkdir macosx
cp -a MicroPeak.app macosx/
cp -a $(MACOSX_README) macosx/ReadMe-MicroPeak.rtf
cp -a $(MACOSX_INSTALL) macosx
mkdir -p macosx/Doc
cp -a $(DOC) macosx/Doc
cp -p Info.plist macosx/MicroPeak.app/Contents
cp -p $(MACOSX_DRIVERS) macosx
mkdir -p macosx/MicroPeak-$(VERSION) macosx/MicroPeak.app/Contents/Resources/Java
cp -p $(MACOSX_ICONS) macosx/MicroPeak.app/Contents/Resources
cp -p $(FATJAR) macosx/MicroPeak.app/Contents/Resources/Java/micropeak.jar
cp -p libaltos.dylib macosx/MicroPeak.app/Contents/Resources/Java
cp -p $(ALTOSLIB_CLASS) macosx/MicroPeak.app/Contents/Resources/Java
cp -p $(ALTOSUILIB_CLASS) macosx/MicroPeak.app/Contents/Resources/Java
cp -p $(JFREECHART_CLASS) macosx/MicroPeak.app/Contents/Resources/Java
cp -p $(JCOMMON_CLASS) macosx/MicroPeak.app/Contents/Resources/Java
cp -p $(MACOSX_EXTRA) macosx/MicroPeak-$(VERSION)
genisoimage -D -V MicroPeak-$(VERSION) -no-pad -r -apple -o $@ macosx
$(WINDOWS_DIST): $(WINDOWS_FILES) micropeak-windows.nsi
-rm -f $@
makensis -Omicropeak-windows.log "-XOutFile $@" "-DVERSION=$(VERSION)" micropeak-windows.nsi || (cat micropeak-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
Manifest.txt: Makefile
echo 'Main-Class: org.altusmetrum.micropeak.MicroPeak' > $@
echo "Class-Path: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(JCOMMON)/jcommon.jar $(JFREECHART)/jfreechart.jar" >> $@
Manifest-fat.txt:
echo 'Main-Class: org.altusmetrum.micropeak.MicroPeak' > $@
echo "Class-Path: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) jcommon.jar jfreechart.jar" >> $@

408
micropeak/MicroData.java Normal file
View File

@@ -0,0 +1,408 @@
/*
* 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 org.altusmetrum.micropeak;
import java.lang.*;
import java.io.*;
import java.util.*;
import org.altusmetrum.altoslib_14.*;
import org.altusmetrum.altosuilib_14.*;
public class MicroData {
public int ground_pressure;
public int min_pressure;
AltosUIFlightSeries flight_series;
AltosFlightStats flight_stats;
AltosCalData cal_data;
private double time_step;
private ArrayList<Integer> bytes;
public int nsamples;
public int log_id;
String name;
String unique_id;
public static final int LOG_ID_MICROPEAK = 0;
public static final int LOG_ID_MICROKITE = 1;
public static final int LOG_ID_MICROPEAK2 = 2;
public static final double CLOCK_MP1 = 0.096;
public static final double CLOCK_MP2 = 0.1;
public class FileEndedException extends Exception {
}
public class NonHexcharException extends Exception {
}
public class InvalidCrcException extends Exception {
}
private int getc(InputStream f) throws IOException, FileEndedException {
int c = f.read();
if (c == -1)
throw new FileEndedException();
bytes.add(c);
return c;
}
private int get_nonwhite(InputStream f) throws IOException, FileEndedException {
int c;
for (;;) {
c = getc(f);
if (!Character.isWhitespace(c))
return c;
}
}
private int get_hexc(InputStream f) throws IOException, FileEndedException, NonHexcharException {
int c = get_nonwhite(f);
if ('0' <= c && c <= '9')
return c - '0';
if ('a' <= c && c <= 'f')
return c - 'a' + 10;
if ('A' <= c && c <= 'F')
return c - 'A' + 10;
throw new NonHexcharException();
}
private static final int POLY = 0x8408;
private int log_crc(int crc, int b) {
int i;
for (i = 0; i < 8; i++) {
if (((crc & 0x0001) ^ (b & 0x0001)) != 0)
crc = (crc >> 1) ^ POLY;
else
crc = crc >> 1;
b >>= 1;
}
return crc & 0xffff;
}
int file_crc;
private int get_hex(InputStream f) throws IOException, FileEndedException, NonHexcharException {
int a = get_hexc(f);
int b = get_hexc(f);
int h = (a << 4) + b;
file_crc = log_crc(file_crc, h);
return h;
}
private boolean find_header(InputStream f) throws IOException, FileEndedException {
for (;;) {
if (get_nonwhite(f) == 'M' && get_nonwhite(f) == 'P')
return true;
}
}
private int get_32(InputStream f) throws IOException, FileEndedException, NonHexcharException {
int v = 0;
for (int i = 0; i < 4; i++) {
v += get_hex(f) << (i * 8);
}
return v;
}
private int get_16(InputStream f) throws IOException, FileEndedException, NonHexcharException {
int v = 0;
for (int i = 0; i < 2; i++) {
v += get_hex(f) << (i * 8);
}
return v;
}
private String get_line(InputStream f) throws IOException, FileEndedException, NonHexcharException {
int c;
StringBuffer line = new StringBuffer();
do {
c = f.read();
} while (Character.isWhitespace(c));
do {
line.append((char) c);
c = f.read();
} while (!Character.isWhitespace(c));
return new String(line);
}
private int swap16(int i) {
return ((i << 8) & 0xff00) | ((i >> 8) & 0xff);
}
public boolean crc_valid;
public boolean log_empty;
int mix_in (int high, int low) {
return high - (high & 0xffff) + low;
}
boolean closer (int target, int a, int b) {
return Math.abs (target - a) < Math.abs(target - b);
}
public double altitude(double time) {
if (flight_series.altitude_series == null)
return 0.0;
return flight_series.altitude_series.value(time);
}
public double altitude(int i) {
return altitude(time(i));
}
public String name() {
return name;
}
public double pressure(int i) {
if (flight_series.pressure_series == null)
return 0.0;
return flight_series.pressure_series.value(time(i));
}
public double height(double time) {
if (flight_series.height_series == null)
return 0.0;
return flight_series.height_series.value(time);
}
public double height(int i) {
return height(time(i));
}
public int length() {
if (flight_series.pressure_series == null)
return 0;
return flight_series.pressure_series.size();
}
/* Use the recorded apogee pressure for stats so that it agrees with the device */
public double apogee_pressure() {
return min_pressure;
}
public double apogee_altitude() {
return AltosConvert.pressure_to_altitude(apogee_pressure());
}
public double apogee_height() {
return apogee_altitude() - cal_data.ground_altitude;
}
public double speed(double time) {
if (flight_series.speed_series == null)
return 0.0;
return flight_series.speed_series.value(time);
}
public double speed(int i) {
return speed(time(i));
}
public double acceleration(double time) {
if (flight_series.accel_series == null)
return 0.0;
return flight_series.accel_series.value(time);
}
public double acceleration(int i) {
return acceleration(time(i));
}
public double time(int i) {
return i * time_step;
}
public void save (OutputStream f) throws IOException {
for (int c : bytes)
f.write(c);
f.write('\n');
}
public boolean is_empty() {
boolean empty = true;
for (int c : bytes) {
if (!Character.isWhitespace(c) && c != 'f')
empty = false;
}
return empty;
}
public void export (Writer f) throws IOException {
PrintWriter pw = new PrintWriter(f);
pw.printf(" Time, Press(Pa), Height(m), Height(f), Speed(m/s), Speed(mph), Speed(mach), Accel(m/s²), Accel(ft/s²), Accel(g)\n");
for (AltosTimeValue ptv : flight_series.pressure_series) {
double height = height(ptv.time);
double speed = speed(ptv.time);
double accel = acceleration(ptv.time);
pw.printf("%6.3f,%10.0f,%10.1f,%10.1f,%11.2f,%11.2f,%12.4f,%12.2f,%13.2f,%10.4f\n",
ptv.time,
ptv.value,
height,
AltosConvert.meters_to_feet(height),
speed,
AltosConvert.meters_to_mph(speed),
AltosConvert.meters_to_mach(speed),
accel,
AltosConvert.meters_to_feet(accel),
AltosConvert.meters_to_g(accel));
}
}
public void set_name(String name) {
this.name = name;
}
public MicroData() {
ground_pressure = 101000;
min_pressure = 101000;
cal_data = new AltosCalData();
flight_series = new AltosUIFlightSeries(cal_data);
}
public MicroData (InputStream f, String name) throws IOException, InterruptedException, NonHexcharException, FileEndedException {
this.name = name;
bytes = new ArrayList<Integer>();
cal_data = new AltosCalData();
flight_series = new AltosUIFlightSeries(cal_data);
if (!find_header(f))
throw new IOException("No MicroPeak data header found");
try {
file_crc = 0xffff;
ground_pressure = get_32(f);
min_pressure = get_32(f);
nsamples = get_16(f);
log_id = nsamples >> 12;
nsamples &= 0xfff;
if (log_id == LOG_ID_MICROPEAK2) {
int nsamples_high = get_16(f);
nsamples |= (nsamples_high << 12);
}
cal_data.set_ground_pressure(ground_pressure);
switch (log_id) {
case LOG_ID_MICROPEAK:
time_step = 2 * CLOCK_MP1;
break;
case LOG_ID_MICROKITE:
time_step = 200 * CLOCK_MP1;
break;
case LOG_ID_MICROPEAK2:
time_step = CLOCK_MP2;
break;
default:
throw new IOException(String.format("Unknown device type: %d", log_id));
}
cal_data.set_ticks_per_sec(1/time_step);
cal_data.set_tick(0);
cal_data.set_boost_tick();
int cur = ground_pressure;
cal_data.set_tick(0);
flight_series.set_time(cal_data.time());
flight_series.set_pressure(cur);
for (int i = 0; i < nsamples; i++) {
int k = get_16(f);
int same = mix_in(cur, k);
int up = mix_in(cur + 0x10000, k);
int down = mix_in(cur - 0x10000, k);
if (closer (cur, same, up)) {
if (closer (cur, same, down))
cur = same;
else
cur = down;
} else {
if (closer (cur, up, down))
cur = up;
else
cur = down;
}
cal_data.set_tick(i+1);
flight_series.set_time(cal_data.time());
flight_series.set_pressure(cur);
}
int current_crc = swap16(~file_crc & 0xffff);
int crc = get_16(f);
crc_valid = (crc == current_crc);
if (!crc_valid && is_empty()) {
crc_valid = true;
nsamples = 0;
}
if (log_id == LOG_ID_MICROPEAK2) {
unique_id = get_line(f);
}
flight_series.finish();
/* Build states */
flight_series.set_time(0);
flight_series.set_state(AltosLib.ao_flight_boost);
if (flight_series.speed_series != null && flight_series.speed_series.max() != null) {
flight_series.set_time(flight_series.speed_series.max().time);
flight_series.set_state(AltosLib.ao_flight_coast);
}
flight_series.set_time(flight_series.height_series.max().time);
flight_series.set_state(AltosLib.ao_flight_drogue);
cal_data.set_tick(nsamples);
flight_series.set_time(cal_data.time());
flight_series.set_state(AltosLib.ao_flight_landed);
flight_series.set_min_pressure(min_pressure);
flight_series.finish();
flight_stats = new AltosFlightStats(flight_series);
} catch (FileEndedException fe) {
throw new IOException("File Ended Unexpectedly");
}
}
}

View File

@@ -0,0 +1,60 @@
/*
* 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 org.altusmetrum.micropeak;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import org.altusmetrum.altosuilib_14.*;
public class MicroDeviceDialog extends AltosDeviceDialog {
public AltosDevice[] devices() {
java.util.List<MicroUSB> list = MicroUSB.list();
if (list == null) {
JOptionPane.showMessageDialog(frame,
"libaltos failed to load",
"Helper Library Failed",
JOptionPane.ERROR_MESSAGE);
return new AltosDevice[0];
}
int num_devices = list.size();
AltosDevice[] devices = new AltosDevice[num_devices];
for (int i = 0; i < num_devices; i++)
devices[i] = list.get(i);
return devices;
}
public MicroDeviceDialog (Frame in_frame, Component location) {
super(in_frame, location, 0);
}
public static AltosDevice show (Component frameComp) {
Frame frame = JOptionPane.getFrameForComponent(frameComp);
MicroDeviceDialog dialog;
dialog = new MicroDeviceDialog (frame, frameComp);
dialog.setVisible(true);
return dialog.getValue();
}
}

View File

@@ -0,0 +1,308 @@
/*
* 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 org.altusmetrum.micropeak;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
import org.altusmetrum.altoslib_14.*;
import org.altusmetrum.altosuilib_14.*;
public class MicroDownload extends AltosUIDialog implements Runnable, ActionListener, MicroSerialLog, WindowListener {
MicroPeak owner;
Container pane;
AltosDevice device;
JButton cancel;
MicroData data;
MicroSerial serial;
LinkedList<Integer> log_queue = new LinkedList<Integer>();
Runnable log_run;
JTextArea serial_log;
JLabel status_value;
int log_column;
public void windowActivated(WindowEvent e) {
}
public void windowClosed(WindowEvent e) {
setVisible(false);
dispose();
}
public void windowClosing(WindowEvent e) {
}
public void windowDeactivated(WindowEvent e) {
}
public void windowDeiconified(WindowEvent e) {
}
public void windowIconified(WindowEvent e) {
}
public void windowOpened(WindowEvent e) {
}
private void done_internal() {
if (data != null && data.crc_valid) {
if (data.nsamples == 0) {
JOptionPane.showMessageDialog(owner,
"No Flight Data Present",
"Empty Log",
JOptionPane.WARNING_MESSAGE);
} else {
status_value.setText("Received MicroPeak Data");
owner = owner.SetData(data);
MicroSave save = new MicroSave(owner, data);
if (save.runDialog())
owner.SetName(data.name);
}
} else {
JOptionPane.showMessageDialog(owner,
"Download Failed",
"Flight data corrupted",
JOptionPane.ERROR_MESSAGE);
}
setVisible(false);
dispose();
}
public void drain_queue() {
for (;;) {
int c;
synchronized(this) {
if (log_queue.isEmpty()) {
log_run = null;
break;
}
c = log_queue.remove();
}
if (c == '\r')
continue;
if (c == '\0')
continue;
String s;
if (c == '\n') {
s = "\n";
log_column = 0;
} else if (' ' <= c && c <= '~') {
byte[] bytes = new byte[1];
bytes[0] = (byte) c;
s = new String(bytes, AltosLib.unicode_set);
log_column += 1;
} else {
s = String.format("\\0x%02x", c & 0xff);
log_column += 5;
}
serial_log.append(s);
if (log_column > 40) {
serial_log.append("\n");
log_column = 0;
}
}
}
public void log_char(int c) {
synchronized(this) {
log_queue.add(c);
if (log_run == null) {
log_run = new Runnable() {
public void run() {
drain_queue();
}
};
SwingUtilities.invokeLater(log_run);
}
}
}
public void done() {
Runnable r = new Runnable() {
public void run() {
try {
done_internal();
} catch (Exception ex) {
}
}
};
SwingUtilities.invokeLater(r);
}
public void run() {
try {
for (;;) {
try {
data = new MicroData(serial, device.toShortString());
if (data != null && data.crc_valid)
break;
} catch (MicroData.NonHexcharException nhe) {
}
}
write_thread.join();
} catch (FileNotFoundException fe) {
} catch (IOException ioe) {
} catch (InterruptedException ie) {
} catch (MicroData.FileEndedException fee) {
}
serial.close();
done();
}
Thread serial_thread;
Thread write_thread;
public class SerialWriter implements Runnable {
MicroSerial serial;
public void run () {
try {
Thread.sleep(100);
serial.write('l');
serial.write('\n');
serial.flush();
} catch (InterruptedException ie) {
}
}
public SerialWriter(MicroSerial serial) {
this.serial = serial;
}
}
public void start() {
serial.set_log(this);
serial_thread = new Thread(this);
serial_thread.start();
SerialWriter writer = new SerialWriter(serial);
write_thread = new Thread(writer);
write_thread.start();
}
public void actionPerformed(ActionEvent ae) {
if (serial_thread != null) {
serial.close();
serial_thread.interrupt();
}
setVisible(false);
}
public MicroDownload(MicroPeak owner, AltosDevice device, MicroSerial serial) {
super (owner, "Download MicroPeak Data", false);
int y = 0;
GridBagConstraints c;
Insets il = new Insets(4,4,4,4);
Insets ir = new Insets(4,4,4,4);
this.owner = owner;
this.device = device;
this.serial = serial;
pane = getScrollablePane();
pane.setLayout(new GridBagLayout());
c = new GridBagConstraints();
c.gridx = 0; c.gridy = y;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LINE_START;
c.insets = il;
JLabel device_label = new JLabel("Device:");
pane.add(device_label, c);
c = new GridBagConstraints();
c.gridx = 1; c.gridy = y;
c.fill = GridBagConstraints.NONE;
c.weightx = 1;
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
JLabel device_value = new JLabel(device.toString());
pane.add(device_value, c);
y++;
c = new GridBagConstraints();
c.gridx = 0; c.gridy = y;
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 0;
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
JLabel help_text = new JLabel(
"<html><i>Turn on the MicroPeak and place the LED inside the<br>" +
"opening in the top of the MicroPeak USB adapter.<br> " +
"Verify that the blue LED in the side of the USB adapter<br>" +
"is blinking along with the orange LED on the MicroPeak.</i></html>");
// help_text.setEditable(false);
pane.add(help_text, c);
y++;
c = new GridBagConstraints();
c.gridx = 0; c.gridy = y;
c.gridwidth = 2;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
status_value = new JLabel("Waiting for MicroPeak data...");
pane.add(status_value, c);
y++;
serial_log = new JTextArea(10, 20);
serial_log.setEditable(false);
JScrollPane serial_scroll = new JScrollPane(serial_log);
serial_scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
c = new GridBagConstraints();
c.gridx = 0; c.gridy = y;
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.BOTH;
c.weightx = 1;
c.weighty = 1;
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
pane.add(serial_scroll, c);
y++;
cancel = new JButton("Cancel");
c = new GridBagConstraints();
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.EAST;
c.gridx = 0; c.gridy = y;
c.gridwidth = GridBagConstraints.REMAINDER;
Insets ic = new Insets(4,4,4,4);
c.insets = ic;
pane.add(cancel, c);
y++;
cancel.addActionListener(this);
pack();
setLocationRelativeTo(owner);
setVisible(true);
start();
}
}

106
micropeak/MicroExport.java Normal file
View File

@@ -0,0 +1,106 @@
/*
* 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 org.altusmetrum.micropeak;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.altusmetrum.altoslib_14.*;
import org.altusmetrum.altosuilib_14.*;
public class MicroExport extends JFileChooser {
JFrame frame;
MicroData data;
public static void export(File file, MicroData data) throws FileNotFoundException, IOException {
FileWriter fw = new FileWriter(file);
data.export(fw);
fw.close();
}
public boolean runDialog() {
int ret;
setSelectedFile(new File(AltosLib.replace_extension(data.name, ".csv")));
for (;;) {
ret = showSaveDialog(frame);
if (ret != APPROVE_OPTION)
return false;
File file;
String filename;
file = getSelectedFile();
if (file == null)
continue;
if (!file.getName().contains(".")) {
String fullname = file.getPath();
file = new File(fullname.concat(".csv"));
}
filename = file.getName();
if (file.exists()) {
if (file.isDirectory()) {
JOptionPane.showMessageDialog(frame,
String.format("\"%s\" is a directory",
filename),
"Directory",
JOptionPane.ERROR_MESSAGE);
continue;
}
int r = JOptionPane.showConfirmDialog(frame,
String.format("\"%s\" already exists. Overwrite?",
filename),
"Overwrite file?",
JOptionPane.YES_NO_OPTION);
if (r != JOptionPane.YES_OPTION)
continue;
if (!file.canWrite()) {
JOptionPane.showMessageDialog(frame,
String.format("\"%s\" is not writable",
filename),
"File not writable",
JOptionPane.ERROR_MESSAGE);
continue;
}
}
try {
export(file, data);
return true;
} catch (FileNotFoundException fe) {
JOptionPane.showMessageDialog(frame,
fe.getMessage(),
"Cannot create file",
JOptionPane.ERROR_MESSAGE);
} catch (IOException ioe) {
}
}
}
public MicroExport(JFrame frame, MicroData data) {
this.frame = frame;
this.data = data;
setDialogTitle("Export MicroPeak Data File");
setFileFilter(new FileNameExtensionFilter("MicroPeak CSV file",
"csv"));
setCurrentDirectory(AltosUIPreferences.logdir());
}
}

53
micropeak/MicroFile.java Normal file
View File

@@ -0,0 +1,53 @@
/*
* Copyright © 2013 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 org.altusmetrum.micropeak;
import java.io.*;
import java.util.*;
import org.altusmetrum.altoslib_14.*;
import org.altusmetrum.altosuilib_14.*;
public class MicroFile {
public static File make(MicroData data, File directory, int year, int month, int day) {
String unique = "";
if (data != null && data.unique_id != null)
unique = String.format("-%s", data.unique_id);
for (int sequence = 1;; sequence++) {
String s = String.format("%04d-%02d-%02d%s-flight-%03d.mpd",
year, month, day, unique, sequence);
File file = new File(directory, s);
if (!file.exists())
return file;
}
}
public static File make(MicroData data, File directory) {
Calendar cal = Calendar.getInstance();
return make(data, directory, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH));
}
public static File make(MicroData data) {
return make(data, AltosUIPreferences.logdir());
}
public static File make() {
return make(null);
}
}

View File

@@ -0,0 +1,56 @@
/*
* 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 org.altusmetrum.micropeak;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
import org.altusmetrum.altoslib_14.*;
import org.altusmetrum.altosuilib_14.*;
public class MicroFileChooser extends JFileChooser {
JFrame frame;
String filename;
File file;
public String filename() {
return filename;
}
public File file() {
return file;
}
public File runDialog() {
int ret;
ret = showOpenDialog(frame);
if (ret == APPROVE_OPTION)
return getSelectedFile();
return null;
}
public MicroFileChooser(JFrame in_frame) {
frame = in_frame;
setDialogTitle("Select MicroPeak Data File");
setFileFilter(new FileNameExtensionFilter("MicroPeak data file",
"mpd"));
setCurrentDirectory(AltosUIPreferences.last_logdir());
}
}

38
micropeak/MicroFrame.java Normal file
View File

@@ -0,0 +1,38 @@
/*
* 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 org.altusmetrum.micropeak;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import org.altusmetrum.altosuilib_14.*;
public class MicroFrame extends AltosUIFrame {
static String[] micro_icon_names = {
"/altusmetrum-micropeak-16.png",
"/altusmetrum-micropeak-32.png",
"/altusmetrum-micropeak-48.png",
"/altusmetrum-micropeak-64.png",
"/altusmetrum-micropeak-128.png",
"/altusmetrum-micropeak-256.png"
};
static { set_icon_names(micro_icon_names); }
}

View 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[@]}"}

View File

@@ -0,0 +1 @@
APPLAM.O

392
micropeak/MicroPeak.java Normal file
View File

@@ -0,0 +1,392 @@
/*
* 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 org.altusmetrum.micropeak;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
import org.altusmetrum.altoslib_14.*;
import org.altusmetrum.altosuilib_14.*;
public class MicroPeak extends MicroFrame implements ActionListener, ItemListener, AltosFilterListener {
File filename;
AltosGraph graph;
AltosUIEnable enable;
AltosFlightStatsTable statsTable;
MicroRaw raw;
MicroData data;
Container container;
JTabbedPane pane;
JMenuBar menu_bar;
static int number_of_windows;
/* File menu */
final static String open_command = "open";
final static String save_command = "save";
final static String export_command = "export";
final static String preferences_command = "preferences";
final static String close_command = "close";
final static String exit_command = "exit";
static final String[][] file_menu_entries = new String[][] {
{ "Open", open_command },
{ "Save a Copy", save_command },
{ "Export Data", export_command },
{ "Preferences", preferences_command },
{ "Close", close_command },
{ "Exit", exit_command },
};
/* Download menu */
final static String download_command = "download";
final static String download_label = "Download";
static final String[][] download_menu_entries = new String[][] {
{ download_label, download_command }
};
MicroPeak SetData(MicroData data) {
MicroPeak mp = this;
if (this.data != null) {
mp = new MicroPeak();
return mp.SetData(data);
}
this.data = data;
if (data.flight_series == null)
System.out.printf("no data in flight\n");
if (data.flight_stats == null)
System.out.printf("no stats in flight\n");
graph.set_data(data.flight_stats, data.flight_series);
statsTable.set_stats(data.flight_stats);
raw.setData(data);
setTitle(data.name);
return this;
}
void SetName(String name) {
graph.setName(name);
setTitle(name);
}
private static MicroData ReadFile(File filename) throws IOException, FileNotFoundException {
MicroData data = null;
FileInputStream fis = new FileInputStream(filename);
try {
data = new MicroData((InputStream) fis, filename.getName());
AltosUIPreferences.set_last_logdir(filename);
} catch (MicroData.NonHexcharException nhe) {
data = null;
} catch (MicroData.FileEndedException nhe) {
data = null;
} catch (InterruptedException ie) {
data = null;
} finally {
fis.close();
}
return data;
}
private void OpenFile(File filename) {
try {
SetData(ReadFile(filename));
} catch (FileNotFoundException fne) {
JOptionPane.showMessageDialog(this,
fne.getMessage(),
"Cannot open file",
JOptionPane.ERROR_MESSAGE);
} catch (IOException ioe) {
JOptionPane.showMessageDialog(this,
ioe.getMessage(),
"File Read Error",
JOptionPane.ERROR_MESSAGE);
}
}
private void SelectFile() {
MicroFileChooser chooser = new MicroFileChooser(this);
File file = chooser.runDialog();
if (file != null)
OpenFile(file);
}
private void Preferences() {
new AltosUIConfigure(this);
}
private void DownloadData() {
AltosDevice device = MicroDeviceDialog.show(this);
MicroSerial serial = null;
try {
serial = new MicroSerial(device);
} catch (FileNotFoundException fe) {
JOptionPane.showMessageDialog(this,
fe.getMessage(),
"Cannot open device",
JOptionPane.ERROR_MESSAGE);
return;
}
new MicroDownload(this, device, serial);
}
private void no_data() {
JOptionPane.showMessageDialog(this,
"No data available",
"No data",
JOptionPane.INFORMATION_MESSAGE);
}
private void Save() {
if (data == null) {
no_data();
return;
}
MicroSave save = new MicroSave (this, data);
if (save.runDialog())
SetName(data.name);
}
private void Export() {
if (data == null) {
no_data();
return;
}
MicroExport export = new MicroExport (this, data);
export.runDialog();
}
private static void CommandGraph(File file) {
MicroPeak m = new MicroPeak();
m.OpenFile(file);
}
private static void CommandExport(File file) {
try {
MicroData d = ReadFile(file);
if (d != null) {
File csv = new File(AltosLib.replace_extension(file.getPath(), ".csv"));
try {
System.out.printf ("Export \"%s\" to \"%s\"\n", file.getPath(), csv.getPath());
MicroExport.export(csv, d);
} catch (FileNotFoundException fe) {
System.err.printf("Cannot create file \"%s\" (%s)\n", csv.getName(), fe.getMessage());
} catch (IOException ie) {
System.err.printf("Cannot write file \"%s\" (%s)\n", csv.getName(), ie.getMessage());
}
}
} catch (IOException ie) {
System.err.printf("Cannot read file \"%s\" (%s)\n", file.getName(), ie.getMessage());
}
}
private void Close() {
setVisible(false);
dispose();
--number_of_windows;
if (number_of_windows == 0)
System.exit(0);
}
public void actionPerformed(ActionEvent ev) {
if (open_command.equals(ev.getActionCommand()))
SelectFile();
else if (save_command.equals(ev.getActionCommand()))
Save();
else if (export_command.equals(ev.getActionCommand()))
Export();
else if (preferences_command.equals(ev.getActionCommand()))
Preferences();
else if (close_command.equals(ev.getActionCommand()))
Close();
else if (exit_command.equals(ev.getActionCommand()))
System.exit(0);
else if (download_command.equals(ev.getActionCommand()))
DownloadData();
}
public void itemStateChanged(ItemEvent e) {
}
/* OSXAdapter interfaces */
public void macosx_file_handler(String path) {
CommandGraph(new File(path));
}
public void macosx_quit_handler() {
System.exit(0);
}
public void macosx_preferences_handler() {
Preferences();
}
public void filter_changed(double speed_filter, double accel_filter) {
data.flight_series.set_filter(speed_filter, accel_filter);
graph.filter_changed();
data.flight_stats = new AltosFlightStats(data.flight_series);
statsTable.filter_changed(data.flight_stats);
}
public double speed_filter() {
if (data != null && data.flight_series != null)
return data.flight_series.speed_filter_width;
return 4.0;
}
public double accel_filter() {
if (data != null && data.flight_series != null)
return data.flight_series.accel_filter_width;
return 1.0;
}
private void add_menu(JMenu menu, String label, String action) {
JMenuItem item = new JMenuItem(label);
menu.add(item);
item.addActionListener(this);
item.setActionCommand(action);
}
private void make_menu(String label, String[][] items) {
JMenu menu = new JMenu(label);
for (int i = 0; i < items.length; i++) {
if (MAC_OS_X) {
if (items[i][1].equals("exit"))
continue;
if (items[i][1].equals("preferences"))
continue;
}
add_menu(menu, items[i][0], items[i][1]);
}
menu_bar.add(menu);
}
public MicroPeak() {
++number_of_windows;
register_for_macosx_events();
AltosUIPreferences.set_component(this);
container = getContentPane();
pane = new JTabbedPane();
setTitle("MicroPeak");
menu_bar = new JMenuBar();
setJMenuBar(menu_bar);
make_menu("File", file_menu_entries);
if (MAC_OS_X) {
make_menu(download_label, download_menu_entries);
} else {
JButton download_button = new JButton (download_label);
download_button.setActionCommand(download_command);
download_button.addActionListener(this);
menu_bar.add(download_button);
}
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
statsTable.tell_closing();
raw.tell_closing();
Close();
}
});
enable = new AltosUIEnable(this);
graph = new AltosGraph(enable);
statsTable = new AltosFlightStatsTable();
raw = new MicroRaw();
pane.add(graph.panel, "Graph");
pane.add(enable, "Configure Graph");
pane.add(statsTable, "Statistics");
JScrollPane scroll = new JScrollPane(raw);
pane.add(scroll, "Raw Data");
pane.doLayout();
pane.validate();
container.add(pane);
container.doLayout();
container.validate();
doLayout();
validate();
Insets i = getInsets();
Dimension ps = pane.getPreferredSize();
ps.width += i.left + i.right;
ps.height += i.top + i.bottom;
setSize(ps);
pack();
setVisible(true);
}
public static void help(int code) {
System.out.printf("Usage: micropeak [OPTION] ... [FILE]...\n");
System.out.printf(" Options:\n");
System.out.printf(" --csv\tgenerate comma separated output for spreadsheets, etc\n");
System.out.printf(" --graph\tgraph a flight\n");
System.exit(code);
}
public static void main(final String[] args) {
boolean opened = false;
boolean graphing = true;
try {
UIManager.setLookAndFeel(AltosUIPreferences.look_and_feel());
} catch (Exception e) {
}
for (int i = 0; i < args.length; i++) {
if (args[i].equals("--help"))
help(0);
else if (args[i].equals("--export"))
graphing = false;
else if (args[i].equals("--graph"))
graphing = true;
else if (args[i].startsWith("--"))
help(1);
else {
File file = new File(args[i]);
try {
if (graphing)
CommandGraph(file);
else
CommandExport(file);
opened = true;
} catch (Exception e) {
System.err.printf("Error processing \"%s\": %s %s\n",
file.getName(), e.toString(), e.getMessage());
e.printStackTrace();
}
}
}
if (!opened)
new MicroPeak();
}
}

55
micropeak/MicroRaw.java Normal file
View File

@@ -0,0 +1,55 @@
/*
* Copyright © 2013 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 org.altusmetrum.micropeak;
import java.awt.*;
import java.io.*;
import javax.swing.*;
import org.altusmetrum.altoslib_14.*;
import org.altusmetrum.altosuilib_14.*;
public class MicroRaw extends JTextArea implements AltosFontListener {
public void font_size_changed(int font_size) {
setFont(AltosUILib.table_value_font);
}
public void setData(MicroData data) {
StringWriter sw = new StringWriter();
try {
data.export(sw);
setRows(data.length());
setText(sw.toString());
} catch (IOException ie) {
setText(String.format("Error writing data: %s", ie.getMessage()));
}
setCaretPosition(0);
}
public void tell_closing() {
AltosUIPreferences.unregister_font_listener(this);
}
public MicroRaw() {
super(1, 30);
setFont(AltosUILib.table_value_font);
setEditable(false);
AltosUIPreferences.register_font_listener(this);
}
}

109
micropeak/MicroSave.java Normal file
View File

@@ -0,0 +1,109 @@
/*
* 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 org.altusmetrum.micropeak;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
import org.altusmetrum.altoslib_14.*;
import org.altusmetrum.altosuilib_14.*;
public class MicroSave extends JFileChooser {
JFrame frame;
MicroData data;
public static void save(File file, MicroData data) throws FileNotFoundException, IOException {
FileOutputStream fos = new FileOutputStream(file);
data.save(fos);
fos.close();
}
public boolean runDialog() {
int ret;
for (;;) {
ret = showSaveDialog(frame);
if (ret != APPROVE_OPTION)
return false;
File file;
String filename;
file = getSelectedFile();
if (file == null)
continue;
if (!file.getName().contains(".")) {
String fullname = file.getPath();
file = new File(fullname.concat(".mpd"));
}
filename = file.getName();
if (file.exists()) {
if (file.isDirectory()) {
JOptionPane.showMessageDialog(frame,
String.format("\"%s\" is a directory",
filename),
"Directory",
JOptionPane.ERROR_MESSAGE);
continue;
}
int r = JOptionPane.showConfirmDialog(frame,
String.format("\"%s\" already exists. Overwrite?",
filename),
"Overwrite file?",
JOptionPane.YES_NO_OPTION);
if (r != JOptionPane.YES_OPTION)
continue;
if (!file.canWrite()) {
JOptionPane.showMessageDialog(frame,
String.format("\"%s\" is not writable",
filename),
"File not writable",
JOptionPane.ERROR_MESSAGE);
continue;
}
}
try {
save(file, data);
AltosUIPreferences.set_last_logdir(file.getParentFile());
data.set_name(filename);
return true;
} catch (FileNotFoundException fe) {
JOptionPane.showMessageDialog(frame,
fe.getMessage(),
"Cannot create file",
JOptionPane.ERROR_MESSAGE);
} catch (IOException ioe) {
}
}
}
public MicroSave(JFrame frame, MicroData data) {
this.frame = frame;
this.data = data;
setDialogTitle("Save MicroPeak Data File");
setFileFilter(new FileNameExtensionFilter("MicroPeak data file",
"mpd"));
setCurrentDirectory(AltosUIPreferences.last_logdir());
setSelectedFile(MicroFile.make(data));
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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 org.altusmetrum.micropeak;
import java.util.*;
import java.io.*;
import libaltosJNI.*;
import org.altusmetrum.altosuilib_14.*;
public class MicroSerial extends InputStream {
SWIGTYPE_p_altos_file file;
private MicroSerialLog log;
public int read() {
if (file == null)
return -1;
int c = libaltos.altos_getchar(file, 0);
if (Thread.interrupted())
return -1;
if (c == -1)
return -1;
if (AltosUIPreferences.serial_debug)
System.out.printf("%c", c);
if (log != null)
log.log_char(c);
return c;
}
public void write(char c) {
libaltos.altos_putchar(file, c);
}
public void flush() {
libaltos.altos_flush(file);
}
public void close() {
if (file != null) {
libaltos.altos_close(file);
file = null;
}
}
public void set_log(MicroSerialLog log) {
this.log = log;
}
public MicroSerial(AltosDevice device) throws FileNotFoundException {
file = device.open();
log = null;
if (file == null) {
final String message = device.getErrorString();
throw new FileNotFoundException(String.format("%s (%s)",
device.toShortString(),
message));
}
}
}

View File

@@ -0,0 +1,29 @@
/*
* 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 org.altusmetrum.micropeak;
import java.util.*;
import java.io.*;
import libaltosJNI.*;
import org.altusmetrum.altosuilib_14.*;
public interface MicroSerialLog {
public void log_char(int c);
}

155
micropeak/MicroUSB.java Normal file
View File

@@ -0,0 +1,155 @@
/*
* 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 org.altusmetrum.micropeak;
import java.util.*;
import libaltosJNI.*;
import org.altusmetrum.altoslib_14.*;
import org.altusmetrum.altosuilib_14.*;
public class MicroUSB extends altos_device implements AltosDevice {
static boolean initialized = false;
static boolean loaded_library = false;
public static boolean load_library() {
if (!initialized) {
try {
System.loadLibrary("altos");
libaltos.altos_init();
loaded_library = true;
} catch (UnsatisfiedLinkError e) {
try {
System.loadLibrary("altos64");
libaltos.altos_init();
loaded_library = true;
} catch (UnsatisfiedLinkError e2) {
loaded_library = false;
}
}
initialized = true;
}
return loaded_library;
}
public String toString() {
String name = getName();
if (name == null)
name = "Altus Metrum";
return String.format("%-24.24s %s",
name, getPath());
}
public String toShortString() {
String name = getName();
if (name == null)
name = "Altus Metrum";
return String.format("%s %s",
name, getPath());
}
public String getErrorString() {
altos_error error = new altos_error();
libaltos.altos_get_last_error(error);
return String.format("%s (%d)", error.getString(), error.getCode());
}
public SWIGTYPE_p_altos_file open() {
return libaltos.altos_open(this);
}
private boolean isFTDI() {
int vid = getVendor();
int pid = getProduct();
if (vid == 0x0403 && pid == 0x6015)
return true;
return false;
}
private boolean isMicro() {
int vid = getVendor();
int pid = getProduct();
if (vid == AltosLib.vendor_altusmetrum &&
pid == AltosLib.product_mpusb)
return true;
return false;
}
public boolean matchProduct(int product) {
return isFTDI() || isMicro();
}
public int hashCode() {
return getVendor() ^ getProduct() ^ getSerial() ^ getPath().hashCode();
}
public boolean equals(Object o) {
if (o == null)
return false;
if (!(o instanceof MicroUSB))
return false;
MicroUSB other = (MicroUSB) o;
return getVendor() == other.getVendor() &&
getProduct() == other.getProduct() &&
getSerial() == other.getSerial() &&
getPath().equals(other.getPath());
}
static java.util.List<MicroUSB> list() {
if (!load_library())
return null;
ArrayList<MicroUSB> device_list = new ArrayList<MicroUSB>();
SWIGTYPE_p_altos_list list;
list = libaltos.altos_ftdi_list_start();
if (list != null) {
for (;;) {
MicroUSB device = new MicroUSB();
if (libaltos.altos_list_next(list, device) == 0)
break;
if (device.isFTDI())
device_list.add(device);
}
libaltos.altos_list_finish(list);
}
list = libaltos.altos_list_start();
if (list != null) {
for (;;) {
MicroUSB device = new MicroUSB();
if (libaltos.altos_list_next(list, device) == 0)
break;
if (device.isMicro())
device_list.add(device);
}
libaltos.altos_list_finish(list);
}
return device_list;
}
}

61
micropeak/ReadMe-Mac.rtf Normal file
View File

@@ -0,0 +1,61 @@
{\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 Liberation Sans{\*\falt Arial};}{\f5\froman\fprq2\fcharset0 Helvetica{\*\falt Arial};}{\f6\froman\fprq2\fcharset0 Helvetica LT Std;}{\f7\fnil\fprq2\fcharset0 SimSun;}{\f8\fnil\fprq2\fcharset0 Arial Unicode MS;}{\f9\fnil\fprq2\fcharset0 Helvetica{\*\falt Arial};}{\f10\fnil\fprq2\fcharset0 Helvetica LT Std;}{\f11\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\af8\langfe1081\dbch\af11\afs24\alang1033\loch\f3\fs24\lang1033 Normal;}
{\s15\sbasedon0\snext16\ql\nowidctlpar\hyphpar0\sb240\sa120\keepn\ltrpar\cf0\kerning1\dbch\af8\langfe1081\dbch\af11\afs24\alang1033\loch\f4\fs28 Heading;}
{\s16\sbasedon0\snext16\sl276\slmult1\ql\nowidctlpar\hyphpar0\sb0\sa140\ltrpar\cf0\kerning1\dbch\af8\langfe1081\dbch\af11\afs24\alang1033\loch\f3\fs24 Text Body;}
{\s17\sbasedon16\snext17\sl276\slmult1\ql\nowidctlpar\hyphpar0\sb0\sa140\ltrpar\cf0\kerning1\dbch\af8\langfe1081\dbch\af11\afs24\alang1033\loch\f3\fs24 List;}
{\s18\sbasedon0\snext18\ql\nowidctlpar\hyphpar0\sb120\sa120\ltrpar\cf0\i\kerning1\dbch\af8\langfe1081\dbch\af11\afs24\alang1033\loch\f3\fs24 Caption;}
{\s19\sbasedon0\snext19\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af8\langfe1081\dbch\af11\afs24\alang1033\loch\f3\fs24 Index;}
}{\*\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\yr0\mo0\dy0\hr0\min0}{\revtim\yr2018\mo10\dy5\hr19\min22}{\printim\yr0\mo0\dy0\hr0\min0}}{\*\userprops}\deftab720
\hyphauto0\viewscale150
{\*\pgdsctbl
{\pgdsc0\pgdscuse451\pgwsxn12240\pghsxn15840\marglsxn1440\margrsxn1440\margtsxn1440\margbsxn1440\pgdscnxt0 Default Style;}}
\formshade{\*\pgdscno0}\paperh15840\paperw12240\margl1440\margr1440\margt1440\margb1440\sectd\sbknone\sectunlocked1\pgndec\pgwsxn12240\pghsxn15840\marglsxn1440\margrsxn1440\margtsxn1440\margbsxn1440\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc
{\*\ftnsep\chftnsep}\pgndec\pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af8\langfe1081\dbch\af11\afs24\alang1033\loch\f3\fs24\lang1033\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640{\cf0\kerning1\dbch\af8\langfe1081\dbch\af9\afs24\alang1033\rtlch \ltrch\loch\fs24\loch\f5\hich\af5
Installing MicroPeak software for Mac OS X computers}
\par \pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af8\langfe1081\dbch\af11\afs24\alang1033\loch\f3\fs24\lang1033\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\cf0\kerning1\dbch\af8\langfe1081\dbch\af9\afs24\alang1033\rtlch \ltrch\loch\fs24\loch\f5\hich\af5
\par \pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af8\langfe1081\dbch\af11\afs24\alang1033\loch\f3\fs24\lang1033{\cf0\kerning1\dbch\af7\langfe1081\dbch\af10\afs24\alang1033\rtlch \ltrch\loch\fs24\lang1033\loch\f6\hich\af6
The MicroPeak distribution for Mac OS X consists of:}
\par \pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af8\langfe1081\dbch\af11\afs24\alang1033\loch\f3\fs24\lang1033\cf0\kerning1\dbch\af7\langfe1081\dbch\af10\afs24\alang1033\rtlch \ltrch\loch\fs24\lang1033\loch\f6\hich\af6
\par \pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af8\langfe1081\dbch\af11\afs24\alang1033\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\af10\afs24\alang1033\rtlch \ltrch\loch\fs24\lang1033\loch\f6\hich\af6
The MicroPeak application}
\par \pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af8\langfe1081\dbch\af11\afs24\alang1033\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\af10\afs24\alang1033\rtlch \ltrch\loch\fs24\lang1033\loch\f6\hich\af6
Mac OS X driver for FTDI USB devices}
\par \pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af8\langfe1081\dbch\af11\afs24\alang1033\loch\f3\fs24\lang1033\li720\ri0\lin720\rin0\fi0\cf0\kerning1\dbch\af8\langfe1081\dbch\af10\afs24\alang1033\rtlch \ltrch\loch\fs24\loch\f6\hich\af6
\par \pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af8\langfe1081\dbch\af11\afs24\alang1033\loch\f3\fs24\lang1033\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640{\cf0\kerning1\dbch\af7\langfe1081\dbch\af9\afs24\alang1033\rtlch \ltrch\loch\fs24\lang1033\loch\f5\hich\af5
Install the MicroPeak 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\af9\afs24\alang1033\rtlch \ltrch\loch\fs24\lang1033\loch\f5\hich\af5
r}{\cf0\kerning1\dbch\af7\langfe1081\dbch\af9\afs24\alang1033\rtlch \ltrch\loch\fs24\lang1033\loch\f5\hich\af5
wards if you choose.}
\par \pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af8\langfe1081\dbch\af11\afs24\alang1033\loch\f3\fs24\lang1033\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\cf0\kerning1\dbch\af8\langfe1081\dbch\af9\afs24\alang1033\rtlch \ltrch\loch\fs24\loch\f5\hich\af5
\par \pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af8\langfe1081\dbch\af11\afs24\alang1033\loch\f3\fs24\lang1033\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640{\cf0\kerning1\dbch\af8\langfe1081\dbch\af9\afs24\alang1033\rtlch \ltrch\loch\fs24\loch\f5\hich\af5
To communicate with the MicroPeak serial adapter, you need to installed the FTDI device drivers, which is done by double-clicking on the FTDIUSBSerialDriver disk image. Inside that is the FTDI USB Serial Driver package. Double click on that and it will guide you through the installation process.}
\par \pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af8\langfe1081\dbch\af11\afs24\alang1033\loch\f3\fs24\lang1033\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\cf0\kerning1\dbch\af8\langfe1081\dbch\af9\afs24\alang1033\rtlch \ltrch\loch\fs24\loch\f5\hich\af5
\par \pard\plain \s0\ql\nowidctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af8\langfe1081\dbch\af11\afs24\alang1033\loch\f3\fs24\lang1033\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640{\cf0\kerning1\dbch\af8\langfe1081\dbch\af9\afs24\alang1033\rtlch \ltrch\loch\fs24\loch\f5\hich\af5
Thanks for choosing AltusMetrum products!}
\par }

View File

@@ -0,0 +1,11 @@
[Desktop Entry]
Type=Application
Name=MicroPeak
GenericName=MicroPeak Download and Analysis
Comment=View and log data from MicroPeak altimeters
Icon=%icondir%/altusmetrum-micropeak.svg
Exec=%bindir%/micropeak %F
Terminal=false
MimeType=application/vnd.altusmetrum.micropeak
Categories=Education;Electronics;Science;
Keywords=Rocket;Altimeter

7
micropeak/mdwn.tmpl Normal file
View File

@@ -0,0 +1,7 @@
[[!inline pages="./%version%/release-notes-%version%.html" rss="no" raw="yes" ]]
- Available Files:
- [Windows Installer](/MicroPeak/releases/%version%/MicroPeak-Windows-%version_dash%.exe)
- [Mac OS X Package](/MicroPeak/releases/%version%/MicroPeak-Mac-%version%.dmg)
- [Linux](/MicroPeak/releases/%version%/MicroPeak-Linux-%version%.sh)
- [Source Snapshot](http://git.gag.com/?p=fw/altos;a=snapshot;h=refs/tags/%version%;sf=tgz)

4
micropeak/micropeak-fat Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
me=`which "$0"`
dir=`dirname "$me"`
exec java -cp "$dir/*" -Djava.library.path="$dir" -jar "$dir"/micropeak-fat.jar "$@"

View File

@@ -0,0 +1,211 @@
!addplugindir ../altosui/Instdrv/NSIS/Plugins
!addincludedir ../altosui/Instdrv/NSIS/Includes
!include x64.nsh
!include java.nsh
!include refresh-sh.nsh
!define REG_NAME "MicroPeak"
!define PROG_ID "org.altusmetrum.micropeak.1"
!define PROG_ID_MPD "org.altusmetrum.micropeak.mpd.1"
!define FAT_NAME "micropeak-fat.jar"
!define WIN_APP_ICON "altusmetrum-micropeak.ico"
!define WIN_APP_EXE "altusmetrum-micropeak.exe"
!define WIN_MPD_EXE "application-vnd.altusmetrum.micropeak.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 "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 "FTDI USB Driver"
SetOutPath $INSTDIR
File "CDM_v2.12.00_WHQL_Certified.exe"
StrCpy $2 "$INSTDIR\CDM_v2.12.00_WHQL_Certified.exe"
ExecWait $2
SectionEnd
Section "Firmware"
SetOutPath $INSTDIR
File "../src/micropeak/micropeak-v0.1-${VERSION}.ihx"
File "../src/microsplash/microsplash-v1.0-${VERSION}.ihx"
SectionEnd
Section "Documentation"
SetOutPath $INSTDIR
File "../doc/micropeak.pdf"
SectionEnd
Section "File Associations"
${DisableX64FSRedirection}
SetOutPath $INSTDIR
File "../icon/${WIN_MPD_EXE}"
; application elements
DeleteRegKey HKCR "${PROG_ID}"
DeleteRegKey HKCR "${PROG_ID_MPD}"
WriteRegStr HKCR "${PROG_ID_MPD}" "" "MicroPeak Data File"
WriteRegStr HKCR "${PROG_ID_MPD}" "FriendlyTypeName" "MicroPeak Data File"
WriteRegStr HKCR "${PROG_ID_MPD}\CurVer" "" "${PROG_ID_MPD}"
WriteRegStr HKCR "${PROG_ID_MPD}\DefaultIcon" "" '"$INSTDIR\${WIN_MPD_EXE}",-101'
WriteRegExpandStr HKCR "${PROG_ID_MPD}\shell\play\command" "" '"$INSTDIR\${WIN_APP_EXE}" "%1"'
; .mpd elements
WriteRegStr HKCR ".mpd" "" "${PROG_ID_MPD}"
WriteRegStr HKCR ".mpd" "PerceivedType" "MicroPeak Data File"
WriteRegStr HKCR ".mpd" "Content Type" "application/vnd.altusmetrum.micropeak"
WriteRegStr HKCR ".mpd\OpenWithProgids" "${PROG_ID_MPD}" ""
WriteRegStr HKCR ".mpd\${PROG_ID_MPD}" "" "${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}"
DeleteRegKey HKCR "${PROG_ID_MPD}"
DeleteRegKey HKCR ".mpd\${PROG_ID_MPD}"
DeleteRegValue HKCR ".mpd\OpenWithProgids" "${PROG_ID_MPD}"
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

43
micropeak/micropeak.1 Normal file
View File

@@ -0,0 +1,43 @@
.\"
.\" Copyright © 2013 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.
.\"
.\"
.TH MICROPEAK 1 "micropeak" ""
.SH NAME
micropeak \- MicroPeak logging altimeter download and analysis
.SH SYNOPSIS
.B "micropeak"
.SH DESCRIPTION
.I micropeak
connects to a MicroPeak USB adapter for MicroPeak data download.
It provides a menu-oriented
user interface to download and analyze data logged on a MicroPeak
altimeter.
.SH USAGE
When connected to a MicroPeak USB adapter,
.I micropeak
can download data from a MicroPeak device, save it to a file and graph
data from saved files.
.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 ~/AltusMetrum). Files are named using the current date and a
unique flight number with a '.mpd' extension.
.SH AUTHOR
Keith Packard