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

27
telegps/.gitignore vendored Normal file
View File

@@ -0,0 +1,27 @@
windows/
linux/
macosx/
fat/
Manifest.txt
Manifest-fat.txt
AltosVersion.java
Info.plist
libaltosJNI
classes
telegps
telegps-test
telegps-jdb
classtelegps.stamp
telegps-windows.nsi
TeleGPS-Linux-*.tar.bz2
TeleGPS-Linux-*.sh
TeleGPS-Mac-*.zip
TeleGPS-Windows-*.exe
*.desktop
telegps-windows.log
*.dll
*.dylib
*.so
*.jar
*.class
*.dmg

73
telegps/Info.plist.in Normal file
View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
<plist version="0.9">
<dict>
<key>CFBundleName</key>
<string>TeleGPS</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.telegps</string>
<key>CFBundleSignature</key>
<string>Altu</string>
<key>CFBundleGetInfoString</key>
<string>TeleGPS version @VERSION@</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleIconFile</key>
<string>altusmetrum-telegps.icns</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>Telemetry</string>
<key>CFBundleTypeIconFile</key>
<string>application-vnd.altusmetrum.telemetry.icns</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>telem</string>
</array>
<key>CFBundleTypeRole</key>
<string>Editor</string>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Eeprom</string>
<key>CFBundleTypeIconFile</key>
<string>application-vnd.altusmetrum.eeprom.icns</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>eeprom</string>
</array>
<key>CFBundleTypeRole</key>
<string>Editor</string>
</dict>
</array>
<key>Java</key>
<dict>
<key>MainClass</key>
<string>org.altusmetrum.telegps.TeleGPS</string>
<key>JVMVersion</key>
<string>1.5+</string>
<key>ClassPath</key>
<array>
<string>$JAVAROOT/telegps.jar</string>
<string>$JAVAROOT/freetts.jar</string>
</array>
<key>VMOptions</key>
<array>
<string>-Xms512M</string>
<string>-Xmx512M</string>
<string>-Dosgi.clean=true</string>
</array>
</dict>
</dict>
</plist>

356
telegps/Makefile.am Normal file
View File

@@ -0,0 +1,356 @@
# location of code signing key, et al
JAVAROOT=classes
AM_JAVACFLAGS=$(JAVAC_VERSION_FLAGS) -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked
man_MANS=telegps.1
altoslibdir=$(libdir)/altos
CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../altoslib/*:../altosuilib/*:../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar:$(FREETTS)/freetts.jar"
bin_SCRIPTS=telegps
telegpsdir=$(datadir)/java
telegps_JAVA= \
TeleGPS.java \
TeleGPSStatus.java \
TeleGPSStatusUpdate.java \
TeleGPSInfo.java \
TeleGPSState.java \
TeleGPSConfig.java \
TeleGPSConfigUI.java \
TeleGPSPreferences.java \
TeleGPSGraphUI.java \
TeleGPSDisplayThread.java
JFREECHART_CLASS= \
jfreechart.jar
JCOMMON_CLASS=\
jcommon.jar
FREETTS_CLASS= \
cmudict04.jar \
cmulex.jar \
cmu_time_awb.jar \
cmutimelex.jar \
cmu_us_kal.jar \
en_us.jar \
freetts.jar
JAR=telegps.jar
FATJAR=telegps-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-telegps-16.png \
$(ICONDIR)/altusmetrum-telegps-32.png \
$(ICONDIR)/altusmetrum-telegps-48.png \
$(ICONDIR)/altusmetrum-telegps-64.png \
$(ICONDIR)/altusmetrum-telegps-128.png\
$(ICONDIR)/altusmetrum-telegps-256.png
# icon base names for jar
ICONJAR= \
-C $(ICONDIR) altusmetrum-telegps-16.png \
-C $(ICONDIR) altusmetrum-telegps-32.png \
-C $(ICONDIR) altusmetrum-telegps-48.png \
-C $(ICONDIR) altusmetrum-telegps-64.png \
-C $(ICONDIR) altusmetrum-telegps-128.png\
-C $(ICONDIR) altusmetrum-telegps-256.png
WINDOWS_ICONS =\
../icon/altusmetrum-telegps.ico \
../icon/altusmetrum-telegps.exe
../icon/application-vnd.altusmetrum.eeprom.ico \
../icon/application-vnd.altusmetrum.eeprom.exe \
../icon/application-vnd.altusmetrum.telemetry.ico \
../icon/application-vnd.altusmetrum.telemetry.exe
MACOSX_ICONS =\
../icon/altusmetrum-telegps.icns \
../icon/application-vnd.altusmetrum.eeprom.icns \
../icon/application-vnd.altusmetrum.telemetry.icns
LINUX_ICONS =\
$(ICONDIR)/altusmetrum-altosui.svg \
$(ICONDIR)/application-vnd.altusmetrum.eeprom.svg \
$(ICONDIR)/application-vnd.altusmetrum.telemetry.svg
LINUX_MIMETYPE =\
$(ICONDIR)/org-altusmetrum-mimetypes.xml
# Firmware
FIRMWARE_TD_3_0=$(top_srcdir)/src/teledongle-v3.0/teledongle-v3.0-$(VERSION).ihx
FIRMWARE_TD=$(FIRMWARE_TD_3_0)
FIRMWARE_TBT_3_0=$(top_srcdir)/src/telebt-v3.0/telebt-v3.0-$(VERSION).ihx
FIRMWARE_TBT_4_0=$(top_srcdir)/src/telebt-v4.0/telebt-v4.0-$(VERSION).ihx
FIRMWARE_TBT=$(FIRMWARE_TBT_3_0) $(FIRMWARE_TBT_4_0)
FIRMWARE_TGPS_1_0=$(top_srcdir)/src/telegps-v1.0/telegps-v1.0-$(VERSION).ihx
FIRMWARE_TGPS_2_0=$(top_srcdir)/src/telegps-v2.0/telegps-v2.0-$(VERSION).ihx
FIRMWARE_TGPS_3_0=$(top_srcdir)/src/telegps-v3.0/telegps-v3.0-$(VERSION).ihx
FIRMWARE_TGPS=$(FIRMWARE_TGPS_1_0) $(FIRMWARE_TGPS_2_0) $(FIRMWARE_TGPS_3_0)
FIRMWARE=$(FIRMWARE_TGPS) $(FIRMWARE_TD) $(FIRMWARE_TBT)
desktopdir = $(datadir)/applications
desktop_file = altusmetrum-telegps.desktop
desktop_SCRIPTS = $(desktop_file)
all-local: telegps-test telegps-jdb $(JAR) $(MDWN)
clean-local:
-rm -rf classes $(JAR) $(FATJAR) \
TeleGPS-Linux-*.tar.bz2 TeleGPS-Mac-*.dmg TeleGPS-Windows-*.exe \
altoslib_*.jar altosuilib_*.jar \
$(JFREECHART_CLASS) $(JCOMMON_CLASS) $(FREETTS_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt \
telegps telegps-test telegps-jdb macosx linux windows telegps-windows.log \
telegps-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=TeleGPS-Linux-$(VERSION).tar.bz2
LINUX_SH=TeleGPS-Linux-$(VERSION).sh
MACOSX_DIST=TeleGPS-Mac-$(VERSION).dmg
WINDOWS_DIST=TeleGPS-Windows-$(VERSION_DASH).exe
MDWN=$(VERSION).mdwn
MDWNTMPL=mdwn.tmpl
TELEGPS_DOC=$(top_srcdir)/doc/telegps.pdf
DOC=$(TELEGPS_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=telegps-fat $(desktop_file).in
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_README) $(DOC) $(MACOSX_ICONS) $(MACOSX_INSTALL)
MACOSX_EXTRA=$(FIRMWARE)
WINDOWS_FILES=$(FAT_FILES) altos.dll altos64.dll $(top_srcdir)/altusmetrum.inf $(top_srcdir)/altusmetrum.cat $(DOC) $(WINDOWS_ICONS)
if FATINSTALL
FATTARGET=$(FATDIR)/TeleGPS/releases/$(VERSION)
LINUX_SH_TARGET=$(FATTARGET)/$(LINUX_SH)
MACOSX_DIST_TARGET=$(FATTARGET)/$(MACOSX_DIST)
WINDOWS_DIST_TARGET=$(FATTARGET)/$(WINDOWS_DIST)
MDWN_TARGET=$(FATDIR)/TeleGPS/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)
telegps: Makefile
echo "#!/bin/sh" > $@
echo 'exec java -Djava.library.path="$(altoslibdir)" -jar "$(telegpsdir)/telegps.jar" "$$@"' >> $@
chmod +x $@
telegps-jdb: Makefile
echo "#!/bin/sh" > $@
echo 'exec jdb -classpath "classes:./*:../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="../libaltos/.libs" org.altusmetrum.telegps.TeleGPS "$$@"' >> $@
chmod +x $@
telegps-test: Makefile
echo "#!/bin/sh" > $@
echo 'exec java -Djava.library.path="../libaltos/.libs" -jar telegps.jar "$$@"' >> $@
chmod +x $@
install-telegpsJAVA: telegps.jar
@$(NORMAL_INSTALL)
test -z "$(telegpsdir)" || $(MKDIR_P) "$(DESTDIR)$(telegpsdir)"
echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(telegpsdir)/telegps.jar'"; \
$(INSTALL_DATA) "$<" "$(DESTDIR)$(telegpsdir)"
$(JAR): classtelegps.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): classtelegps.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
libaltos.so: build-libaltos
-rm -f "$@"
$(LN_S) ../libaltos/.libs/"$@" .
libaltos_i686.so: build-libaltos
-rm -f "$@"
$(LN_S) ../libaltos/.libs/"$@" .
libaltos_amd64.so: build-libaltos
-rm -f "$@"
$(LN_S) ../libaltos/.libs/"$@" .
libaltos_aarch64.so: build-libaltos
-rm -f "$@"
$(LN_S) ../libaltos/.libs/"$@" .
libaltos_armel.so: build-libaltos
-rm -f "$@"
$(LN_S) ../libaltos/.libs/"$@" .
libaltos_armhf.so: build-libaltos
-rm -f "$@"
$(LN_S) ../libaltos/.libs/"$@" .
libaltos.dylib:
-rm -f "$@"
$(LN_S) ../libaltos/"$@" .
altos.dll: build-libaltos
-rm -f "$@"
$(LN_S) ../libaltos/"$@" .
altos64.dll: build-libaltos
-rm -f "$@"
$(LN_S) ../libaltos/"$@" .
build-libaltos:
+cd ../libaltos && make
$(ALTOSLIB_CLASS):
-rm -f "$@"
$(LN_S) ../altoslib/"$@" .
$(ALTOSUILIB_CLASS):
-rm -f "$@"
$(LN_S) ../altosuilib/"$@" .
$(FREETTS_CLASS):
-rm -f "$@"
$(LN_S) "$(FREETTS)"/"$@" .
$(JFREECHART_CLASS):
-rm -f "$@"
$(LN_S) "$(JFREECHART)"/"$@" .
$(JCOMMON_CLASS):
-rm -f "$@"
$(LN_S) "$(JCOMMON)"/"$@" .
$(LINUX_DIST): $(LINUX_FILES) $(LINUX_EXTRA)
-rm -f $@
-rm -rf linux
mkdir -p linux/TeleGPS
cp -p $(LINUX_FILES) linux/TeleGPS
cp -p telegps-fat linux/TeleGPS/telegps
chmod +x linux/TeleGPS/telegps
tar cjf $@ -C linux TeleGPS
$(LINUX_SH): $(LINUX_DIST) $(srcdir)/../altosui/linux-install.sh
sed 's/AltOS/TeleGPS/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 TeleGPS.app macosx/
cp -a $(MACOSX_README) macosx/ReadMe-TeleGPS.rtf
cp -a $(MACOSX_INSTALL) macosx
mkdir -p macosx/Doc
cp -a $(DOC) macosx/Doc
cp -p Info.plist macosx/TeleGPS.app/Contents
mkdir -p macosx/AltOS-$(VERSION) macosx/TeleGPS.app/Contents/Resources/Java
cp -p $(MACOSX_ICONS) macosx/TeleGPS.app/Contents/Resources
cp -p $(FATJAR) macosx/TeleGPS.app/Contents/Resources/Java/telegps.jar
cp -p libaltos.dylib macosx/TeleGPS.app/Contents/Resources/Java
cp -p $(ALTOSLIB_CLASS) macosx/TeleGPS.app/Contents/Resources/Java
cp -p $(ALTOSUILIB_CLASS) macosx/TeleGPS.app/Contents/Resources/Java
cp -p $(FREETTS_CLASS) macosx/TeleGPS.app/Contents/Resources/Java
cp -p $(JFREECHART_CLASS) macosx/TeleGPS.app/Contents/Resources/Java
cp -p $(JCOMMON_CLASS) macosx/TeleGPS.app/Contents/Resources/Java
cp -p $(MACOSX_EXTRA) macosx/AltOS-$(VERSION)
genisoimage -D -V TeleGPS-$(VERSION) -no-pad -r -apple -o $@ macosx
$(WINDOWS_DIST): $(WINDOWS_FILES) telegps-windows.nsi
-rm -f $@
makensis -Otelegps-windows.log "-XOutFile $@" "-DVERSION=$(VERSION)" telegps-windows.nsi || (cat telegps-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.telegps.TeleGPS' > $@
echo "Class-Path: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS)/freetts.jar $(JCOMMON)/jcommon.jar $(JFREECHART)/jfreechart.jar" >> $@
Manifest-fat.txt:
echo 'Main-Class: org.altusmetrum.telegps.TeleGPS' > $@
echo "Class-Path: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) freetts.jar jcommon.jar jfreechart.jar" >> $@

97
telegps/ReadMe-Mac.rtf Normal file
View File

@@ -0,0 +1,97 @@
{\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\fswiss\fprq2\fcharset0 Arial;}{\f6\froman\fprq2\fcharset0 Helvetica{\*\falt Arial};}{\f7\froman\fprq2\fcharset0 Arial;}{\f8\froman\fprq2\fcharset0 Courier New;}{\f9\froman\fprq2\fcharset0 Helvetica LT Std;}{\f10\fnil\fprq2\fcharset0 SimSun;}{\f11\fnil\fprq2\fcharset0 Courier New;}{\f12\fnil\fprq2\fcharset0 Arial Unicode MS;}{\f13\fnil\fprq2\fcharset0 Arial;}{\f14\fnil\fprq2\fcharset0 Helvetica{\*\falt Arial};}{\f15\fnil\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}{\f16\fnil\fprq2\fcharset0 Helvetica LT Std;}}
{\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\widctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f3\fs24\lang1033 Normal;}
{\s1\sbasedon19\snext1\ql\widctlpar\hyphpar0\sb440\sa60\keepn\ltrpar\cf0\b\kerning1\dbch\af12\langfe1081\dbch\af15\afs24\loch\f5\fs34\lang1033 Heading 1;}
{\s2\sbasedon19\snext2\ql\widctlpar\hyphpar0\sb440\sa60\keepn\ltrpar\cf0\b\kerning1\dbch\af12\langfe1081\dbch\af15\afs24\loch\f5\fs28\lang1033 Heading 2;}
{\s3\sbasedon19\snext3\ql\widctlpar\hyphpar0\sb440\sa60\keepn\ltrpar\cf0\b\kerning1\dbch\af12\langfe1081\dbch\af15\afs24\loch\f5\fs24\lang1033 Heading 3;}
{\s4\sbasedon19\snext4\ql\widctlpar\hyphpar0\sb440\sa60\keepn\ltrpar\cf0\b\kerning1\dbch\af12\langfe1081\dbch\af15\afs24\loch\f5\fs24\lang1033 Heading 4;}
{\*\cs15\snext15\super\fs20 Endnote Characters;}
{\*\cs16\snext16\super\fs20 Endnote Anchor;}
{\*\cs17\snext17\super\fs20 Footnote Characters;}
{\*\cs18\snext18\super\fs20 Footnote Anchor;}
{\s19\sbasedon0\snext20\ql\widctlpar\hyphpar0\sb240\sa120\keepn\ltrpar\cf0\kerning1\dbch\af12\langfe1081\dbch\af15\afs24\loch\f4\fs28\lang1033 Heading;}
{\s20\sbasedon0\snext20\sl276\slmult1\ql\widctlpar\hyphpar0\sb0\sa140\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\loch\f3\fs24\lang1033 Text Body;}
{\s21\sbasedon20\snext21\sl276\slmult1\ql\widctlpar\hyphpar0\sb0\sa140\ltrpar\cf0\kerning1\dbch\af12\langfe1081\dbch\af15\afs24\loch\f3\fs24\lang1033 List;}
{\s22\sbasedon0\snext22\ql\widctlpar\hyphpar0\sb120\sa120\ltrpar\cf0\i\kerning1\dbch\af12\langfe1081\dbch\af15\afs24\loch\f3\fs24\lang1033 Caption;}
{\s23\sbasedon0\snext23\ql\widctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af12\langfe1081\dbch\af15\afs24\loch\f3\fs24\lang1033 Index;}
{\s24\snext24\ql\widctlpar\hyphpar0\li720\ri0\lin720\rin0\fi-431\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f6\fs24\lang1033 Arrowhead List;}
{\s25\sbasedon0\snext25\ql\widctlpar\hyphpar0\li1440\ri1440\lin1440\rin1440\fi0\sb0\sa120\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\loch\f3\fs24\lang1033 Block Text;}
{\s26\snext26\ql\widctlpar\hyphpar0\li720\ri0\lin720\rin0\fi-431\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f6\fs24\lang1033 Box List;}
{\s27\snext27\ql\widctlpar\hyphpar0\li720\ri0\lin720\rin0\fi-431\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f6\fs24\lang1033 Bullet List;}
{\s28\snext28\tx1584\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af17\langfe2052\dbch\af12\afs24\alang1081\loch\f3\hich\af3\fs24\lang1033 Chapter Heading;}
{\s29\sbasedon23\snext29\ql\widctlpar\hyphpar0\li720\ri0\lin720\rin0\fi-431\ltrpar\cf0\kerning1\dbch\af12\langfe1081\dbch\af15\afs24\loch\f3\fs24\lang1033 Contents 1;}
{\s30\sbasedon23\snext30\ql\widctlpar\hyphpar0\li1440\ri0\lin1440\rin0\fi-431\ltrpar\cf0\kerning1\dbch\af12\langfe1081\dbch\af15\afs24\loch\f3\fs24\lang1033 Contents 2;}
{\s31\sbasedon23\snext31\ql\widctlpar\hyphpar0\li2160\ri0\lin2160\rin0\fi-431\ltrpar\cf0\kerning1\dbch\af12\langfe1081\dbch\af15\afs24\loch\f3\fs24\lang1033 Contents 3;}
{\s32\sbasedon23\snext32\ql\widctlpar\hyphpar0\li2880\ri0\lin2880\rin0\fi-431\ltrpar\cf0\kerning1\dbch\af12\langfe1081\dbch\af15\afs24\loch\f3\fs24\lang1033 Contents 4;}
{\s33\snext33\qc\nowidctlpar\hyphpar0\sb240\sa120\ltrpar\cf0\b\kerning1\dbch\af12\langfe1081\dbch\af13\afs32\alang1033\loch\f7\fs24\lang1033 Contents Header;}
{\s34\snext34\ql\widctlpar\hyphpar0\li720\ri0\lin720\rin0\fi-431\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f6\fs24\lang1033 Dashed List;}
{\s35\snext35\ql\widctlpar\hyphpar0\li720\ri0\lin720\rin0\fi-431\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f6\fs24\lang1033 Diamond List;}
{\s36\sbasedon0\snext36\ql\widctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\loch\f3\fs24\lang1033 Endnote;}
{\s37\sbasedon0\snext37\ql\widctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\loch\f3\fs20\lang1033 Footnote;}
{\s38\snext38\ql\widctlpar\hyphpar0\li720\ri0\lin720\rin0\fi-431\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f6\fs24\lang1033 Hand List;}
{\s39\snext39\ql\widctlpar\hyphpar0\li720\ri0\lin720\rin0\fi-431\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f6\fs24\lang1033 Heart List;}
{\s40\snext40\ql\widctlpar\hyphpar0\li720\ri0\lin720\rin0\fi-431\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f6\fs24\lang1033 Implies List;}
{\s41\snext41\ql\widctlpar\li720\ri0\lin720\rin0\fi-431\ltrpar\hyphpar0\dbch\af11\cf0\kerning1\langfe2052\dbch\af12\afs24\alang1081\loch\f6\fs24\lang1033 Lower Case List;}
{\s42\snext42\ql\nowidctlpar\hyphpar0\li720\ri0\lin720\rin0\fi-431\ltrpar\cf0\kerning1\dbch\af12\langfe1081\dbch\af15\afs24\alang1033\loch\f3\fs24\lang1033 Lower Roman List;}
{\s43\snext43\ql\nowidctlpar\tx431\hyphpar0\ltrpar\cf0\kerning1\dbch\af12\langfe1081\dbch\af15\afs24\alang1033\loch\f3\fs24\lang1033 Numbered Heading 1;}
{\s44\snext44\ql\nowidctlpar\tx431\hyphpar0\ltrpar\cf0\kerning1\dbch\af12\langfe1081\dbch\af15\afs24\alang1033\loch\f3\fs24\lang1033 Numbered Heading 2;}
{\s45\snext45\ql\nowidctlpar\tx431\hyphpar0\ltrpar\cf0\kerning1\dbch\af12\langfe1081\dbch\af15\afs24\alang1033\loch\f3\fs24\lang1033 Numbered Heading 3;}
{\s46\snext46\ql\widctlpar\hyphpar0\li720\ri0\lin720\rin0\fi-431\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f6\fs24\lang1033 Numbered List;}
{\s47\sbasedon0\snext47\ql\widctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\loch\f8\fs24\lang1033 Plain Text;}
{\s48\sbasedon43\snext48\ql\nowidctlpar\tx1584\hyphpar0\ltrpar\cf0\kerning1\dbch\af12\langfe1081\dbch\af15\afs24\alang1033\loch\f3\fs24 Section Heading;}
{\s49\snext49\ql\widctlpar\hyphpar0\li720\ri0\lin720\rin0\fi-431\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f6\fs24\lang1033 Square List;}
{\s50\snext50\ql\widctlpar\hyphpar0\li720\ri0\lin720\rin0\fi-431\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f6\fs24\lang1033 Star List;}
{\s51\snext51\ql\widctlpar\hyphpar0\li720\ri0\lin720\rin0\fi-431\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f6\fs24\lang1033 Tick List;}
{\s52\snext52\ql\widctlpar\hyphpar0\li720\ri0\lin720\rin0\fi-431\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f6\fs24\lang1033 Triangle List;}
{\s53\sbasedon46\snext53\ql\widctlpar\hyphpar0\li720\ri0\lin720\rin0\fi-431\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\loch\f6\fs24\lang1033 Upper Case List;}
{\s54\sbasedon46\snext54\ql\widctlpar\hyphpar0\li720\ri0\lin720\rin0\fi-431\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\loch\f6\fs24\lang1033 Upper Roman List;}
}{\*\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\min21}{\printim\yr0\mo0\dy0\hr0\min0}}{\*\userprops}\deftab720\deftab720\deftab720\deftab720\deftab720\deftab720\deftab720\deftab720\deftab720\deftab720\deftab720\deftab720\deftab720\deftab720\deftab720\deftab720\deftab720
\hyphauto0\viewscale150
{\*\pgdsctbl
{\pgdsc0\pgdscuse451\pgwsxn12240\pghsxn15840\marglsxn1440\margrsxn1440\margtsxn1440\margbsxn1440\pgdscnxt0 Default Style;}
{\pgdsc1\pgdscuse451\pgndec\pgwsxn12240\pghsxn15840\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\pgdscnxt1 Endnote;}}
\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\aftnnar
{\*\ftnsep\chftnsep}\pgndec\pard\plain \s0\ql\widctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f3\fs24\lang1033\sl240\slmult1\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640{\cf0\kerning1\dbch\af11\langfe1081\dbch\af14\rtlch \ltrch\loch\fs24\lang1033\loch\f6\hich\af6
Installing TeleGPS software for Mac OS X computers}
\par \pard\plain \s0\ql\widctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f3\fs24\lang1033\sl240\slmult1\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\cf0\kerning1\dbch\af11\langfe1081\dbch\af14\rtlch \ltrch\loch\fs24\lang1033\loch\f6\hich\af6
\par \pard\plain \s0\ql\widctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f3\fs24\lang1033{\cf0\kerning1\dbch\af10\langfe1081\dbch\af16\rtlch \ltrch\loch\fs24\lang1033\loch\f9\hich\af9
The TeleGPS distribution for Mac OS X consists of:}
\par \pard\plain \s0\ql\widctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f3\fs24\lang1033\cf0\kerning1\dbch\af10\langfe1081\dbch\af16\rtlch \ltrch\loch\fs24\lang1033\loch\f9\hich\af9
\par \pard\plain \s0\ql\widctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f3\fs24\lang1033{\listtext\pard\plain 1)\tab}\ilvl0\ls1 \li1440\ri0\lin1440\rin0\fi-360\li720\ri0\lin720\rin0\fi-360{\cf0\kerning1\dbch\af10\langfe1081\dbch\af16\rtlch \ltrch\loch\fs24\lang1033\loch\f9\hich\af9
The TeleGPS application}
\par \pard\plain \s0\ql\widctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f3\fs24\lang1033{\listtext\pard\plain 2)\tab}\ilvl0\ls1 \li1440\ri0\lin1440\rin0\fi-360\li720\ri0\lin720\rin0\fi-360{\cf0\kerning1\dbch\af10\langfe1081\dbch\af16\rtlch \ltrch\loch\fs24\lang1033\loch\f9\hich\af9
Current AltOS firmware for TeleGPS products}
\par \pard\plain \s0\ql\widctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f3\fs24\lang1033\cf0\kerning1\dbch\af10\langfe1081\dbch\af16\rtlch \ltrch\loch\fs24\lang1033\loch\f9\hich\af9
\par \pard\plain \s0\ql\widctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f3\fs24\lang1033{\cf0\kerning1\dbch\af10\langfe1081\dbch\af16\rtlch \ltrch\loch\fs24\lang1033\loch\f9\hich\af9
Install the TeleGPS 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\af10\langfe1081\dbch\af16\rtlch \ltrch\loch\fs24\lang1033\loch\f9\hich\af9
r}{\cf0\kerning1\dbch\af10\langfe1081\dbch\af16\rtlch \ltrch\loch\fs24\lang1033\loch\f9\hich\af9
wards if you choose.}
\par \pard\plain \s0\ql\widctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f3\fs24\lang1033\cf0\kerning1\dbch\af11\langfe1081\dbch\af16\rtlch \ltrch\loch\fs24\lang1033\loch\f9\hich\af9
\par \pard\plain \s0\ql\widctlpar\hyphpar0\ltrpar\cf0\kerning1\dbch\af11\langfe1081\dbch\af15\afs24\alang1081\loch\f3\fs24\lang1033\sl240\slmult1\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640{\cf0\kerning1\dbch\af10\langfe1081\dbch\af14\rtlch \ltrch\loch\fs24\lang1033\loch\f6\hich\af6
Thanks for choosing AltusMetrum products!}
\par }

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

777
telegps/TeleGPS.java Normal file
View File

@@ -0,0 +1,777 @@
/*
* 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.telegps;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
import java.text.*;
import org.altusmetrum.altoslib_14.*;
import org.altusmetrum.altosuilib_14.*;
public class TeleGPS
extends AltosUIFrame
implements AltosFlightDisplay, AltosFontListener, AltosUnitsListener, ActionListener, AltosEepromGrapher
{
static String[] telegps_icon_names = {
"/altusmetrum-telegps-16.png",
"/altusmetrum-telegps-32.png",
"/altusmetrum-telegps-48.png",
"/altusmetrum-telegps-64.png",
"/altusmetrum-telegps-128.png",
"/altusmetrum-telegps-256.png"
};
static { set_icon_names(telegps_icon_names); }
static AltosVoice voice;
static AltosVoice voice() {
if (voice == null)
voice = new AltosVoice();
return voice;
}
AltosFlightReader reader;
TeleGPSDisplayThread thread;
boolean idle_mode;
JMenuBar menu_bar;
JMenu file_menu;
JMenu monitor_menu;
JMenu device_menu;
AltosUIFreqList frequencies;
ActionListener frequency_listener;
AltosUIRateList rates;
ActionListener rate_listener;
Container bag;
TeleGPSStatus telegps_status;
TeleGPSStatusUpdate status_update;
JTabbedPane pane;
AltosUIMap map;
TeleGPSInfo gps_info;
TeleGPSState gps_state;
AltosInfoTable info_table;
LinkedList<AltosFlightDisplay> displays;
/* File menu */
final static String new_command = "new";
final static String graph_command = "graph";
final static String export_command = "export";
final static String load_maps_command = "loadmaps";
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[][] {
{ "New Window", new_command },
{ "Graph Data", graph_command },
{ "Export Data", export_command },
{ "Load Maps", load_maps_command },
{ "Preferences", preferences_command },
{ "Close", close_command },
{ "Exit", exit_command },
};
/* Monitor menu */
final static String connect_command = "connect";
final static String disconnect_command = "disconnect";
final static String scan_command = "scan";
static final String[][] monitor_menu_entries = new String[][] {
{ "Connect Device", connect_command },
{ "Disconnect", disconnect_command },
{ "Scan Channels", scan_command },
};
/* Device menu */
final static String download_command = "download";
final static String configure_command = "configure";
final static String flash_command = "flash";
static final String[][] device_menu_entries = new String[][] {
{ "Download Data", download_command },
{ "Configure Device", configure_command },
{ "Flash Device", flash_command },
};
void stop_display() {
if (thread != null && thread.isAlive()) {
thread.interrupt();
try {
thread.join();
} catch (InterruptedException ie) {}
}
thread = null;
}
public void reset() {
for (AltosFlightDisplay display : displays)
display.reset();
}
public void font_size_changed(int font_size) {
for (AltosFlightDisplay display : displays)
display.font_size_changed(font_size);
}
public void units_changed(boolean imperial_units) {
for (AltosFlightDisplay display : displays)
display.units_changed(imperial_units);
}
public void show(AltosState state, AltosListenerState listener_state) {
try {
status_update.saved_state = state;
status_update.saved_listener_state = listener_state;
if (state == null)
state = new AltosState(new AltosCalData());
int i = 0;
for (AltosFlightDisplay display : displays) {
display.show(state, listener_state);
i++;
}
} catch (Exception ex) {
System.out.printf("Exception %s\n", ex.toString());
for (StackTraceElement e : ex.getStackTrace())
System.out.printf("%s\n", e.toString());
}
}
void new_window() {
new TeleGPS();
}
void preferences() {
new TeleGPSPreferences(this, voice());
}
void load_maps() {
new AltosUIMapPreload(this);
}
void disconnect() {
setTitle("TeleGPS");
stop_display();
telegps_status.stop();
telegps_status.disable_receive();
disable_frequency_menu();
disable_rate_menu();
}
void connect_flight(AltosDevice device) {
try {
AltosFlightReader reader = new AltosTelemetryReader(new AltosSerial(device));
set_reader(reader, device, false);
} catch (FileNotFoundException ee) {
JOptionPane.showMessageDialog(this,
ee.getMessage(),
String.format ("Cannot open %s", device.toShortString()),
JOptionPane.ERROR_MESSAGE);
} catch (AltosSerialInUseException si) {
JOptionPane.showMessageDialog(this,
String.format("Device \"%s\" already in use",
device.toShortString()),
"Device in use",
JOptionPane.ERROR_MESSAGE);
} catch (IOException ee) {
JOptionPane.showMessageDialog(this,
String.format ("Unknown I/O error on %s", device.toShortString()),
"Unknown I/O error",
JOptionPane.ERROR_MESSAGE);
} catch (TimeoutException te) {
JOptionPane.showMessageDialog(this,
String.format ("Timeout on %s", device.toShortString()),
"Timeout error",
JOptionPane.ERROR_MESSAGE);
} catch (InterruptedException ie) {
JOptionPane.showMessageDialog(this,
String.format("Interrupted %s", device.toShortString()),
"Interrupted exception",
JOptionPane.ERROR_MESSAGE);
}
}
void connect_idle(AltosDevice device) {
try {
AltosFlightReader reader = new AltosIdleReader(new AltosSerial(device), false);
set_reader(reader, device, true);
} catch (FileNotFoundException ee) {
JOptionPane.showMessageDialog(this,
ee.getMessage(),
String.format ("Cannot open %s", device.toShortString()),
JOptionPane.ERROR_MESSAGE);
} catch (AltosSerialInUseException si) {
JOptionPane.showMessageDialog(this,
String.format("Device \"%s\" already in use",
device.toShortString()),
"Device in use",
JOptionPane.ERROR_MESSAGE);
} catch (IOException ee) {
JOptionPane.showMessageDialog(this,
String.format ("Unknown I/O error on %s", device.toShortString()),
"Unknown I/O error",
JOptionPane.ERROR_MESSAGE);
} catch (TimeoutException te) {
JOptionPane.showMessageDialog(this,
String.format ("Timeout on %s", device.toShortString()),
"Timeout error",
JOptionPane.ERROR_MESSAGE);
} catch (InterruptedException ie) {
JOptionPane.showMessageDialog(this,
String.format("Interrupted %s", device.toShortString()),
"Interrupted exception",
JOptionPane.ERROR_MESSAGE);
}
}
void connect(AltosDevice device) {
if (reader != null)
disconnect();
if (device.matchProduct(AltosLib.product_basestation))
connect_flight(device);
else
connect_idle(device);
}
void connect() {
AltosDevice device = AltosDeviceUIDialog.show(this,
AltosLib.product_any);
if (device == null)
return;
connect(device);
}
public void scan_device_selected(AltosDevice device) {
connect(device);
}
void scan() {
new AltosScanUI(this, false);
}
void download(){
new AltosEepromManage(this, this, AltosLib.product_telegps);
}
void configure() {
new TeleGPSConfig(this);
}
private static AltosFlightSeries make_series(AltosRecordSet set) {
AltosFlightSeries series = new AltosFlightSeries(set.cal_data());
set.capture_series(series);
series.finish();
return series;
}
void export() {
AltosDataChooser chooser = new AltosDataChooser(this);
AltosRecordSet set = chooser.runDialog();
if (set == null)
return;
AltosFlightSeries series = make_series(set);
new AltosCSVUI(this, series, chooser.file());
}
void graph() {
AltosDataChooser chooser = new AltosDataChooser(this);
AltosRecordSet set = chooser.runDialog();
graph_file(this, set, chooser.file());
}
public void graph_flights(AltosEepromList list) {
for (AltosEepromLog log : list) {
if (log.file != null) {
AltosRecordSet set = record_set(log.file);
graph_file(this, set, log.file);
}
}
}
void flash() {
AltosFlashUI.show(this);
}
public void actionPerformed(ActionEvent ev) {
/* File menu */
if (new_command.equals(ev.getActionCommand())) {
new_window();
return;
}
if (preferences_command.equals(ev.getActionCommand())) {
preferences();
return;
}
if (load_maps_command.equals(ev.getActionCommand())) {
load_maps();
return;
}
if (close_command.equals(ev.getActionCommand())) {
close();
return;
}
if (exit_command.equals(ev.getActionCommand()))
System.exit(0);
/* Monitor menu */
if (connect_command.equals(ev.getActionCommand())) {
connect();
return;
}
if (disconnect_command.equals(ev.getActionCommand())) {
disconnect();
return;
}
if (scan_command.equals(ev.getActionCommand())) {
scan();
return;
}
/* Device menu */
if (download_command.equals(ev.getActionCommand())) {
download();
return;
}
if (configure_command.equals(ev.getActionCommand())) {
configure();
return;
}
if (export_command.equals(ev.getActionCommand())) {
export();
return;
}
if (graph_command.equals(ev.getActionCommand())) {
graph();
return;
}
if (flash_command.equals(ev.getActionCommand())) {
flash();
return;
}
}
void enable_frequency_menu(int serial, final AltosFlightReader reader) {
if (frequency_listener != null)
disable_frequency_menu();
frequency_listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
double frequency = frequencies.frequency();
try {
reader.set_frequency(frequency);
} catch (TimeoutException te) {
} catch (InterruptedException ie) {
}
reader.save_frequency();
}
};
frequencies.addActionListener(frequency_listener);
frequencies.set_product("Monitor");
frequencies.set_serial(serial);
frequencies.set_frequency(AltosUIPreferences.frequency(serial));
frequencies.setEnabled(true);
}
void disable_frequency_menu() {
if (frequency_listener != null) {
frequencies.removeActionListener(frequency_listener);
frequencies.setEnabled(false);
frequency_listener = null;
}
}
void enable_rate_menu(int serial, final AltosFlightReader reader) {
if (rate_listener != null)
disable_rate_menu();
rate_listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
int rate = rates.rate();
try {
reader.set_telemetry_rate(rate);
} catch (TimeoutException te) {
} catch (InterruptedException ie) {
}
reader.save_telemetry_rate();
}
};
rates.addActionListener(rate_listener);
rates.set_product("Monitor");
rates.set_serial(serial);
rates.set_rate(AltosUIPreferences.telemetry_rate(serial));
rates.setEnabled(reader.supports_telemetry_rate(AltosLib.ao_telemetry_rate_2400));
}
void disable_rate_menu() {
if (rate_listener != null) {
rates.removeActionListener(rate_listener);
rates.setEnabled(false);
rate_listener = null;
}
}
public void set_reader(AltosFlightReader reader, AltosDevice device, boolean idle_mode) {
this.idle_mode = idle_mode;
status_update = new TeleGPSStatusUpdate(telegps_status);
telegps_status.start(status_update);
setTitle(String.format("TeleGPS %s", reader.name));
thread = new TeleGPSDisplayThread(this, voice(), this, reader);
thread.start();
if (device != null) {
if (idle_mode) {
disable_frequency_menu();
disable_rate_menu();
} else {
enable_frequency_menu(device.getSerial(), reader);
enable_rate_menu(device.getSerial(), reader);
}
}
}
static int number_of_windows;
static public void add_window() {
++number_of_windows;
}
static public void subtract_window() {
--number_of_windows;
if (number_of_windows == 0)
System.exit(0);
}
private void close() {
disconnect();
AltosUIPreferences.unregister_font_listener(this);
AltosPreferences.unregister_units_listener(this);
setVisible(false);
dispose();
subtract_window();
}
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 JMenu 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);
return menu;
}
/* OSXAdapter interfaces */
public void macosx_file_handler(String path) {
process_graph(new File(path));
}
public void macosx_quit_handler() {
System.exit(0);
}
public void macosx_preferences_handler() {
preferences();
}
public TeleGPS() {
AltosUIPreferences.set_component(this);
register_for_macosx_events();
reader = null;
bag = getContentPane();
bag.setLayout(new GridBagLayout());
setTitle("TeleGPS");
menu_bar = new JMenuBar();
setJMenuBar(menu_bar);
file_menu = make_menu("File", file_menu_entries);
monitor_menu = make_menu("Monitor", monitor_menu_entries);
device_menu = make_menu("Device", device_menu_entries);
set_inset(3);
frequencies = new AltosUIFreqList();
frequencies.setEnabled(false);
bag.add(frequencies, constraints (0, 1));
rates = new AltosUIRateList();
rates.setEnabled(false);
bag.add(rates, constraints(1, 1));
next_row();
set_inset(0);
displays = new LinkedList<AltosFlightDisplay>();
int serial = -1;
/* TeleGPS status is always visible */
telegps_status = new TeleGPSStatus();
bag.add(telegps_status, constraints(0, 3, GridBagConstraints.HORIZONTAL));
next_row();
displays.add(telegps_status);
/* The rest of the window uses a tabbed pane to
* show one of the alternate data views
*/
pane = new JTabbedPane();
/* Make the tabbed pane use the rest of the window space */
bag.add(pane, constraints(0, 3, GridBagConstraints.BOTH));
map = new AltosUIMap();
pane.add(map.getName(), map);
displays.add(map);
gps_info = new TeleGPSInfo();
pane.add(gps_info.getName(), gps_info);
displays.add(gps_info);
gps_state = new TeleGPSState();
pane.add(gps_state.getName(), gps_state);
displays.add(gps_state);
info_table = new AltosInfoTable();
pane.add("Table", info_table);
displays.add(info_table);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
AltosUIPreferences.register_font_listener(this);
AltosPreferences.register_units_listener(this);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
close();
}
});
pack();
setVisible(true);
add_window();
}
public TeleGPS(AltosFlightReader reader, boolean idle_mode) {
this();
set_reader(reader, null, idle_mode);
}
public TeleGPS(AltosDevice device) {
this();
connect(device);
}
static AltosRecordSet record_set(File file) {
try {
return AltosLib.record_set(file);
} catch (IOException ie) {
System.out.printf("%s\n", ie.getMessage());
}
return null;
}
static AltosReplayReader replay_file(File file) {
AltosRecordSet set = record_set(file);
if (set == null)
return null;
return new AltosReplayReader(set, file);
}
private static boolean graph_file(TeleGPS telegps, AltosRecordSet set, File file) {
if (set == null)
return false;
if (!set.valid()) {
JOptionPane.showMessageDialog(telegps,
String.format("Failed to parse file %s", file),
"Graph Failed",
JOptionPane.ERROR_MESSAGE);
return false;
}
try {
new TeleGPSGraphUI(set, file);
} catch (IOException e) {
System.out.printf("Exception %s\n", e.toString());
} catch (InterruptedException e) {
System.out.printf("Exception %s\n", e.toString());
return false;
}
return true;
}
static boolean process_graph(File file) {
AltosRecordSet set = record_set(file);
return graph_file(null, set, file);
}
static boolean process_replay(File file) {
AltosReplayReader new_reader = replay_file(file);
if (new_reader == null)
return false;
new TeleGPS(new_reader, true);
return true;
}
static final int process_none = 0;
static final int process_csv = 1;
static final int process_kml = 2;
static final int process_graph = 3;
static final int process_replay = 4;
static final int process_summary = 5;
static final int process_cat = 6;
public static boolean load_library(Frame frame) {
if (!AltosUILib.load_library()) {
JOptionPane.showMessageDialog(frame,
String.format("No AltOS library in \"%s\"",
System.getProperty("java.library.path","<undefined>")),
"Cannot load device access library",
JOptionPane.ERROR_MESSAGE);
return false;
}
return true;
}
public static void help(int code) {
System.out.printf("Usage: altosui [OPTION]... [FILE]...\n");
System.out.printf(" Options:\n");
System.out.printf(" --replay <filename>\t\trelive the glory of past flights \n");
System.out.printf(" --graph <filename>\t\tgraph a flight\n");
System.out.printf(" --csv\tgenerate comma separated output for spreadsheets, etc\n");
System.out.printf(" --kml\tgenerate KML output for use with Google Earth\n");
System.exit(code);
}
public static void main(String[] args) {
int errors = 0;
load_library(null);
try {
UIManager.setLookAndFeel(AltosUIPreferences.look_and_feel());
} catch (Exception e) {
}
boolean any_created = false;
/* Handle batch-mode */
int process = process_none;
for (int i = 0; i < args.length; i++) {
if (args[i].equals("--help"))
help(0);
else if (args[i].equals("--replay"))
process = process_replay;
else if (args[i].equals("--kml"))
process = process_kml;
else if (args[i].equals("--csv"))
process = process_csv;
else if (args[i].equals("--graph"))
process = process_graph;
else if (args[i].equals("--summary"))
process = process_summary;
else if (args[i].equals("--cat"))
process = process_cat;
else if (args[i].startsWith("--"))
help(1);
else {
File file = new File(args[i]);
switch (process) {
case process_none:
case process_graph:
if (!process_graph(file))
++errors;
break;
case process_replay:
if (!process_replay(file))
++errors;
any_created = true;
break;
case process_kml:
++errors;
break;
case process_csv:
++errors;
break;
case process_summary:
++errors;
break;
case process_cat:
++errors;
}
}
}
if (errors != 0)
System.exit(errors);
if (number_of_windows == 0) {
java.util.List<AltosDevice> devices = AltosUSBDevice.list(AltosLib.product_basestation);
if (devices != null)
for (AltosDevice device : devices) {
new TeleGPS(device);
any_created = true;
}
if (number_of_windows == 0)
new TeleGPS();
}
}
}

298
telegps/TeleGPSConfig.java Normal file
View File

@@ -0,0 +1,298 @@
/*
* 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.telegps;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
import java.text.*;
import org.altusmetrum.altoslib_14.*;
import org.altusmetrum.altosuilib_14.*;
public class TeleGPSConfig implements ActionListener {
class int_ref {
int value;
public int get() {
return value;
}
public void set(int i) {
value = i;
}
public int_ref(int i) {
value = i;
}
}
class string_ref {
String value;
public String get() {
return value;
}
public void set(String i) {
value = i;
}
public string_ref(String i) {
value = i;
}
}
JFrame owner;
AltosDevice device;
AltosSerial serial_line;
AltosConfigData data;
TeleGPSConfigUI config_ui;
boolean serial_started;
boolean made_visible;
void start_serial() throws InterruptedException, TimeoutException {
serial_started = true;
}
void stop_serial() throws InterruptedException {
if (!serial_started)
return;
serial_started = false;
}
void update_ui() {
data.set_values(config_ui);
config_ui.set_clean();
if (!made_visible) {
made_visible = true;
config_ui.make_visible();
}
}
int pyro;
final static int serial_mode_read = 0;
final static int serial_mode_save = 1;
final static int serial_mode_reboot = 2;
class SerialData implements Runnable {
TeleGPSConfig config;
int serial_mode;
void callback(String in_cmd) {
final String cmd = in_cmd;
Runnable r = new Runnable() {
public void run() {
if (cmd.equals("abort")) {
abort();
} else if (cmd.equals("all finished")) {
if (serial_line != null)
update_ui();
}
}
};
SwingUtilities.invokeLater(r);
}
void get_data() {
data = null;
try {
start_serial();
data = new AltosConfigData(config.serial_line);
} catch (InterruptedException ie) {
} catch (TimeoutException te) {
try {
stop_serial();
callback("abort");
} catch (InterruptedException ie) {
}
} finally {
try {
stop_serial();
} catch (InterruptedException ie) {
}
}
callback("all finished");
}
void save_data() {
try {
start_serial();
data.save(serial_line, false);
} catch (InterruptedException ie) {
} catch (TimeoutException te) {
} finally {
try {
stop_serial();
} catch (InterruptedException ie) {
}
}
}
void reboot() {
try {
start_serial();
serial_line.printf("r eboot\n");
serial_line.flush_output();
} catch (InterruptedException ie) {
} catch (TimeoutException te) {
} finally {
try {
stop_serial();
serial_line.close();
} catch (InterruptedException ie) {
}
}
}
public void run () {
switch (serial_mode) {
case serial_mode_save:
save_data();
/* fall through ... */
case serial_mode_read:
get_data();
break;
case serial_mode_reboot:
reboot();
break;
}
}
public SerialData(TeleGPSConfig in_config, int in_serial_mode) {
config = in_config;
serial_mode = in_serial_mode;
}
}
void run_serial_thread(int serial_mode) {
SerialData sd = new SerialData(this, serial_mode);
Thread st = new Thread(sd);
st.start();
}
void init_ui () throws InterruptedException, TimeoutException {
config_ui = new TeleGPSConfigUI(owner);
config_ui.addActionListener(this);
serial_line.set_frame(owner);
set_ui();
}
void abort() {
if (serial_line != null) {
serial_line.close();
serial_line = null;
}
JOptionPane.showMessageDialog(owner,
String.format("Connection to \"%s\" failed",
device.toShortString()),
"Connection Failed",
JOptionPane.ERROR_MESSAGE);
config_ui.setVisible(false);
}
void set_ui() throws InterruptedException, TimeoutException {
if (serial_line != null)
run_serial_thread(serial_mode_read);
else
update_ui();
}
double frequency() {
return AltosConvert.radio_to_frequency(data.radio_frequency,
data.radio_setting,
data.radio_calibration,
data.radio_channel);
}
void save_data() {
try {
/* bounds check stuff */
if (config_ui.flight_log_max() > data.log_space()/1024) {
JOptionPane.showMessageDialog(owner,
String.format("Requested flight log, %dk, is larger than the available space, %dk.\n",
config_ui.flight_log_max(),
data.log_space()/1024),
"Maximum Flight Log Too Large",
JOptionPane.ERROR_MESSAGE);
return;
}
/* Pull data out of the UI and stuff back into our local data record */
data.get_values(config_ui);
run_serial_thread(serial_mode_save);
} catch (AltosConfigDataException ae) {
JOptionPane.showMessageDialog(owner,
ae.getMessage(),
"Configuration Data Error",
JOptionPane.ERROR_MESSAGE);
}
}
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
try {
if (cmd.equals("Save")) {
save_data();
} else if (cmd.equals("Reset")) {
set_ui();
} else if (cmd.equals("Reboot")) {
if (serial_line != null)
run_serial_thread(serial_mode_reboot);
} else if (cmd.equals("Close")) {
if (serial_line != null)
serial_line.close();
}
} catch (InterruptedException ie) {
abort();
} catch (TimeoutException te) {
abort();
}
}
public TeleGPSConfig(JFrame given_owner) {
owner = given_owner;
device = AltosDeviceUIDialog.show(owner, AltosLib.product_telegps);
if (device != null) {
try {
serial_line = new AltosSerial(device);
try {
init_ui();
} catch (InterruptedException ie) {
abort();
} catch (TimeoutException te) {
abort();
}
} catch (FileNotFoundException ee) {
JOptionPane.showMessageDialog(owner,
ee.getMessage(),
"Cannot open target device",
JOptionPane.ERROR_MESSAGE);
} catch (AltosSerialInUseException si) {
JOptionPane.showMessageDialog(owner,
String.format("Device \"%s\" already in use",
device.toShortString()),
"Device in use",
JOptionPane.ERROR_MESSAGE);
}
}
}
}

1205
telegps/TeleGPSConfigUI.java Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,212 @@
/*
* 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.telegps;
import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.text.*;
import org.altusmetrum.altoslib_14.*;
import org.altusmetrum.altosuilib_14.*;
public class TeleGPSDisplayThread extends Thread {
Frame parent;
IdleThread idle_thread;
AltosVoice voice;
AltosFlightReader reader;
AltosState state;
int old_state = AltosLib.ao_flight_invalid;
boolean old_gps_ready = false;
AltosListenerState listener_state;
AltosFlightDisplay display;
synchronized void show_safely() {
final AltosState my_state = state;
final AltosListenerState my_listener_state = listener_state;
Runnable r = new Runnable() {
public void run() {
try {
display.show(my_state, my_listener_state);
} catch (Exception ex) {
}
}
};
SwingUtilities.invokeLater(r);
}
void reading_error_internal() {
JOptionPane.showMessageDialog(parent,
String.format("Error reading from \"%s\"", reader.name),
"Telemetry Read Error",
JOptionPane.ERROR_MESSAGE);
}
void reading_error_safely() {
Runnable r = new Runnable() {
public void run() {
try {
reading_error_internal();
} catch (Exception ex) {
}
}
};
SwingUtilities.invokeLater(r);
}
class IdleThread extends Thread {
boolean started;
int report_interval;
long report_time;
public synchronized void report(boolean last) {
if (state == null)
return;
if (state.height() != AltosLib.MISSING) {
if (state.from_pad != null) {
voice.speak("Height %s, bearing %s %d, elevation %d, range %s, .\n",
AltosConvert.height.say(state.gps_height()),
state.from_pad.bearing_words(
AltosGreatCircle.BEARING_VOICE),
(int) (state.from_pad.bearing + 0.5),
(int) (state.elevation + 0.5),
AltosConvert.distance.say(state.range));
} else {
voice.speak("Height %s.\n",
AltosConvert.height.say(state.height()));
}
}
}
long now () {
return System.currentTimeMillis();
}
void set_report_time() {
report_time = now() + report_interval;
}
public void run () {
try {
for (;;) {
if (reader.has_monitor_battery()) {
listener_state.battery = reader.monitor_battery();
show_safely();
}
set_report_time();
for (;;) {
voice.drain();
synchronized (this) {
long sleep_time = report_time - now();
if (sleep_time <= 0)
break;
wait(sleep_time);
}
}
report(false);
}
} catch (InterruptedException ie) {
try {
voice.drain();
} catch (InterruptedException iie) { }
}
}
public synchronized void notice(boolean spoken) {
if (old_state != state.state()) {
report_time = now();
this.notify();
} else if (spoken)
set_report_time();
old_state = state.state();
}
public IdleThread() {
report_interval = 10000;
}
}
synchronized boolean tell() {
boolean ret = false;
if (old_gps_ready != state.gps_ready) {
if (state.gps_ready) {
voice.speak("GPS ready");
ret = true;
}
else if (old_gps_ready) {
voice.speak("GPS lost");
ret = true;
}
old_gps_ready = state.gps_ready;
}
return ret;
}
public void run() {
boolean interrupted = false;
boolean told;
idle_thread = new IdleThread();
idle_thread.start();
try {
for (;;) {
try {
state = reader.read();
if (state == null) {
listener_state.running = false;
break;
}
show_safely();
told = tell();
idle_thread.notice(told);
} catch (ParseException pp) {
System.out.printf("Parse error: %d \"%s\"\n", pp.getErrorOffset(), pp.getMessage());
} catch (AltosCRCException ce) {
++listener_state.crc_errors;
show_safely();
}
}
} catch (InterruptedException ee) {
interrupted = true;
} catch (IOException ie) {
reading_error_safely();
} finally {
if (!interrupted)
idle_thread.report(true);
reader.close(interrupted);
idle_thread.interrupt();
try {
idle_thread.join();
} catch (InterruptedException ie) {}
}
}
public TeleGPSDisplayThread(Frame in_parent, AltosVoice in_voice, AltosFlightDisplay in_display, AltosFlightReader in_reader) {
listener_state = new AltosListenerState();
parent = in_parent;
voice = in_voice;
display = in_display;
reader = in_reader;
display.reset();
}
}

168
telegps/TeleGPSGraphUI.java Normal file
View File

@@ -0,0 +1,168 @@
/*
* Copyright © 2010 Anthony Towns
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
package org.altusmetrum.telegps;
import java.io.*;
import java.util.ArrayList;
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.*;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.ui.RefineryUtilities;
public class TeleGPSGraphUI extends AltosUIFrame implements AltosFontListener, AltosUnitsListener, AltosFilterListener
{
JTabbedPane pane;
AltosGraph graph;
AltosUIEnable enable;
AltosUIMap map;
AltosState state;
AltosFlightStats stats;
AltosFlightStatsTable statsTable;
AltosGPS gps;
boolean has_gps;
void fill_map(AltosFlightSeries flight_series) {
boolean any_gps = false;
AltosGPSTimeValue gtv_last = null;
double gps_pad_altitude = flight_series.cal_data().gps_pad_altitude;;
if (flight_series.gps_series != null) {
for (AltosGPSTimeValue gtv : flight_series.gps_series) {
gtv_last = gtv;
AltosGPS gps = gtv.gps;
if (gps != null &&
gps.locked &&
gps.nsat >= 4) {
if (map == null)
map = new AltosUIMap();
double gps_height = gps.alt - gps_pad_altitude;
int state = (int) flight_series.value_before(AltosFlightSeries.state_name, gtv.time);
map.show(gps, gtv.time, state, gps_height);
this.gps = gps;
has_gps = true;
}
}
}
if (gtv_last != null) {
int state = (int) flight_series.value_after(AltosFlightSeries.state_name, gtv_last.time);
double gps_height = gps.alt - gps_pad_altitude;
if (state == AltosLib.ao_flight_landed)
map.show(gtv_last.gps, gtv_last.time, state, gps_height);
}
}
private void close() {
setVisible(false);
dispose();
TeleGPS.subtract_window();
}
public void font_size_changed(int font_size) {
if (map != null)
map.font_size_changed(font_size);
if (statsTable != null)
statsTable.font_size_changed(font_size);
}
public void units_changed(boolean imperial_units) {
if (map != null)
map.units_changed(imperial_units);
if (enable != null)
enable.units_changed(imperial_units);
}
AltosUIFlightSeries flight_series;
public void filter_changed(double speed_filter, double accel_filter) {
flight_series.set_filter(speed_filter, accel_filter);
graph.filter_changed();
stats = new AltosFlightStats(flight_series);
statsTable.filter_changed(stats);
}
public double speed_filter() {
return flight_series.speed_filter_width;
}
public double accel_filter() {
return flight_series.accel_filter_width;
}
TeleGPSGraphUI(AltosRecordSet set, File file) throws InterruptedException, IOException {
super(file.getName());
AltosCalData cal_data = set.cal_data();
pane = new JTabbedPane();
flight_series = new AltosUIFlightSeries(cal_data);
enable = new AltosUIEnable(this);
set.capture_series(flight_series);
flight_series.finish();
stats = new AltosFlightStats(flight_series);
graph = new AltosGraph(enable, stats, flight_series);
statsTable = new AltosFlightStatsTable(stats);
map = new AltosUIMap();
pane.add("Graph", graph.panel);
pane.add("Configure Graph", enable);
pane.add("Statistics", statsTable);
fill_map(flight_series);
pane.add("Map", map);
setContentPane (pane);
AltosUIPreferences.register_font_listener(this);
AltosPreferences.register_units_listener(this);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
close();
}
});
pack();
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
TeleGPS.add_window();
setVisible(true);
if (state != null)
map.centre(state);
}
}

215
telegps/TeleGPSInfo.java Normal file
View File

@@ -0,0 +1,215 @@
/*
* 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.telegps;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import org.altusmetrum.altoslib_14.*;
import org.altusmetrum.altosuilib_14.*;
public class TeleGPSInfo extends AltosUIFlightTab {
JLabel cur, max;
abstract class Value extends AltosUIUnitsIndicator {
public abstract void show(AltosState state, AltosListenerState listener_state);
public Value (Container container, int y, AltosUnits units, String text) {
super(container, y, units, text, 1, false, 2);
}
}
abstract class DualValue extends AltosUIUnitsIndicator {
public DualValue (Container container, int y, AltosUnits units, String text) {
super(container, y, units, text, 2, false, 1);
}
}
abstract class ValueHold extends DualValue {
public void reset() {
super.reset();
}
public ValueHold (Container container, int y, AltosUnits units, String text) {
super(container, y, units, text);
}
}
class Altitude extends ValueHold {
public double value(AltosState state, int i) {
if (i == 0)
return state.altitude();
else
return state.max_altitude();
}
public Altitude (Container container, int y) {
super (container, y, AltosConvert.height, "Altitude");
}
}
class AscentRate extends ValueHold {
public double value(AltosState state, int i) {
if (i == 0)
return state.gps_ascent_rate();
else
return state.max_gps_ascent_rate();
}
public AscentRate (Container container, int y) {
super (container, y, AltosConvert.speed, "Ascent Rate");
}
}
class GroundSpeed extends ValueHold {
public double value(AltosState state, int i) {
if (i == 0)
return state.gps_ground_speed();
else
return state.max_gps_ground_speed();
}
public GroundSpeed (Container container, int y) {
super (container, y, AltosConvert.speed, "Ground Speed");
}
}
class Course extends AltosUIIndicator {
public void show (AltosState state, AltosListenerState listener_state) {
double course = state.gps_course();
if (course == AltosLib.MISSING)
show("Missing", "Missing");
else
show( String.format("%3.0f°", course),
AltosConvert.bearing_to_words(
AltosConvert.BEARING_LONG,
course));
}
public Course (Container container, int y) {
super (container, y, "Course", 2, false, 1);
}
}
class Lat extends AltosUIIndicator {
String pos(double p, String pos, String neg) {
String h = pos;
if (p < 0) {
h = neg;
p = -p;
}
int deg = (int) Math.floor(p);
double min = (p - Math.floor(p)) * 60.0;
return String.format("%s %4d° %9.6f", h, deg, min);
}
public void show (AltosState state, AltosListenerState listener_state) {
if (state.gps != null && state.gps.connected && state.gps.lat != AltosLib.MISSING)
show(pos(state.gps.lat,"N", "S"));
else
show("Missing");
}
public Lat (Container container, int y) {
super (container, y, "Latitude", 1, false, 2);
}
}
class Lon extends AltosUIIndicator {
String pos(double p, String pos, String neg) {
String h = pos;
if (p < 0) {
h = neg;
p = -p;
}
int deg = (int) Math.floor(p);
double min = (p - Math.floor(p)) * 60.0;
return String.format("%s %4d° %9.6f", h, deg, min);
}
public void show (AltosState state, AltosListenerState listener_state) {
if (state.gps != null && state.gps.connected && state.gps.lon != AltosLib.MISSING)
show(pos(state.gps.lon,"E", "W"));
else
show("Missing");
}
public Lon (Container container, int y) {
super (container, y, "Longitude", 1, false, 2);
}
}
class GPSLocked extends AltosUIIndicator {
public void show (AltosState state, AltosListenerState listener_state) {
if (state == null || state.gps == null)
hide();
else {
int soln = state.gps.nsat;
int nsat = state.gps.cc_gps_sat != null ? state.gps.cc_gps_sat.length : 0;
show("%4d in solution", soln,
"%4d in view", nsat);
set_lights(state.gps.locked && soln >= 4);
}
}
public GPSLocked (Container container, int y) {
super (container, y, "GPS Locked", 2, true, 1);
}
}
public void font_size_changed(int font_size) {
cur.setFont(AltosUILib.label_font);
max.setFont(AltosUILib.label_font);
super.font_size_changed(font_size);
}
public void labels(Container container, int y) {
GridBagLayout layout = (GridBagLayout)(container.getLayout());
GridBagConstraints c;
cur = new JLabel("Current");
cur.setFont(AltosUILib.label_font);
c = new GridBagConstraints();
c.gridx = 2; c.gridy = y;
c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
layout.setConstraints(cur, c);
add(cur);
max = new JLabel("Maximum");
max.setFont(AltosUILib.label_font);
c.gridx = 3; c.gridy = y;
layout.setConstraints(max, c);
add(max);
}
public String getName() {
return "Location";
}
public TeleGPSInfo() {
int y = 0;
labels(this, y++);
add(new Altitude(this, y++));
add(new GroundSpeed(this, y++));
add(new AscentRate(this, y++));
add(new Course(this, y++));
add(new Lat(this, y++));
add(new Lon(this, y++));
add(new GPSLocked(this, y++));
}
}

View File

@@ -0,0 +1,121 @@
/*
* 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.telegps;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
import org.altusmetrum.altosuilib_14.*;
public class TeleGPSPreferences
extends AltosUIConfigure
implements DocumentListener
{
AltosVoice voice;
public JTextField callsign_value;
public JComboBox<String> position_value;
/* DocumentListener interface methods */
public void insertUpdate(DocumentEvent e) {
changedUpdate(e);
}
public void removeUpdate(DocumentEvent e) {
changedUpdate(e);
}
public void changedUpdate(DocumentEvent e) {
if (callsign_value != null)
AltosUIPreferences.set_callsign(callsign_value.getText());
}
public void add_voice() {
/* Voice settings */
pane.add(new JLabel("Voice"), constraints(0, 1));
JRadioButton enable_voice = new JRadioButton("Enable", AltosUIPreferences.voice());
enable_voice.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JRadioButton item = (JRadioButton) e.getSource();
boolean enabled = item.isSelected();
AltosUIPreferences.set_voice(enabled);
if (enabled)
voice.speak_always("Enable voice.");
else
voice.speak_always("Disable voice.");
}
});
pane.add(enable_voice, constraints(1, 1));
enable_voice.setToolTipText("Enable/Disable all audio in-flight announcements");
JButton test_voice = new JButton("Test Voice");
test_voice.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
voice.speak("That's one small step for man; one giant leap for mankind.");
}
});
pane.add(test_voice, constraints(2, 1));
test_voice.setToolTipText("Play a stock audio clip to check volume");
row++;
}
public void add_callsign() {
/* Callsign setting */
pane.add(new JLabel("Callsign"), constraints(0, 1));
callsign_value = new JTextField(AltosUIPreferences.callsign());
callsign_value.getDocument().addDocumentListener(this);
callsign_value.setToolTipText("Callsign sent in packet mode");
pane.add(callsign_value, constraints(1, 2, GridBagConstraints.BOTH));
row++;
}
public void add_bluetooth() {
JButton manage_bluetooth = new JButton("Manage Bluetooth");
manage_bluetooth.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
AltosBTManage.show(owner, AltosBTKnown.bt_known());
}
});
pane.add(manage_bluetooth, constraints(0, 2));
/* in the same row as add_frequencies, so don't bump row */
}
public void add_frequencies() {
JButton manage_frequencies = new JButton("Manage Frequencies");
manage_frequencies.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
AltosConfigFreqUI.show(owner);
}
});
manage_frequencies.setToolTipText("Configure which values are shown in frequency menus");
pane.add(manage_frequencies, constraints(2, 1));
row++;
}
public TeleGPSPreferences(JFrame owner, AltosVoice voice) {
super(owner, "TeleGPS Preferences", "Configure TeleGPS");
this.voice = voice;
}
}

232
telegps/TeleGPSState.java Normal file
View File

@@ -0,0 +1,232 @@
/*
* 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.telegps;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import org.altusmetrum.altoslib_14.*;
import org.altusmetrum.altosuilib_14.*;
public class TeleGPSState extends AltosUIFlightTab {
JLabel cur, max;
abstract class Value extends AltosUIUnitsIndicator {
public Value (Container container, int y, AltosUnits units, String text) {
super(container, y, units, text, 1, false, 2);
}
}
abstract class DualValue extends AltosUIUnitsIndicator {
public DualValue (Container container, int y, AltosUnits units, String text) {
super(container, y, units, text, 2, false, 1);
}
}
abstract class ValueHold extends DualValue {
public ValueHold (Container container, int y, AltosUnits units, String text) {
super(container, y, units, text);
}
}
class Height extends ValueHold {
public double value(AltosState state, int i) {
if (i == 0)
return state.height();
else
return state.max_height();
}
public Height(Container container, int y) {
super(container, y, AltosConvert.height, "Height");
}
}
class Speed extends ValueHold {
public double value(AltosState state, int i) {
if (i == 0)
return state.gps_speed();
else
return state.max_gps_speed();
}
public Speed(Container container, int y) {
super(container, y, AltosConvert.speed, "Speed");
}
}
class Distance extends Value {
public double value(AltosState state, int i) {
if (state.from_pad != null)
return state.from_pad.distance;
else
return AltosLib.MISSING;
}
public Distance(Container container, int y) {
super(container, y, AltosConvert.distance, "Distance");
}
}
class Range extends Value {
public double value(AltosState state, int i) {
return state.range;
}
public Range (Container container, int y) {
super (container, y, AltosConvert.distance, "Range");
}
}
class Bearing extends AltosUIIndicator {
public void show (AltosState state, AltosListenerState listener_state) {
if (state.from_pad != null && state.from_pad.bearing != AltosLib.MISSING) {
show( String.format("%3.0f°", state.from_pad.bearing),
state.from_pad.bearing_words(
AltosGreatCircle.BEARING_LONG));
} else {
show("Missing", "Missing");
}
}
public Bearing (Container container, int y) {
super (container, y, "Bearing", 2, false, 1);
}
}
class Elevation extends AltosUIIndicator {
public void show (AltosState state, AltosListenerState listener_state) {
if (state.elevation == AltosLib.MISSING)
show("Missing");
else
show("%3.0f°", state.elevation);
}
public Elevation (Container container, int y) {
super (container, y, "Elevation", 1, false, 2);
}
}
class FirmwareVersion extends AltosUIIndicator {
public void show(AltosState state, AltosListenerState listener_state) {
AltosCalData cal_data = state.cal_data();
if (cal_data.firmware_version == null)
show("Missing");
else
show(cal_data.firmware_version);
}
public FirmwareVersion(Container container, int y) {
super(container, y, "Firmware Version", 1, false, 2);
}
}
class FlightLogMax extends AltosUIIndicator {
public void show(AltosState state, AltosListenerState listener_state) {
AltosCalData cal_data = state.cal_data();
int storage = cal_data.flight_log_max;
if (storage == AltosLib.MISSING)
show("Missing");
else
show(String.format("%dkB", storage));
}
public FlightLogMax(Container container, int y) {
super(container, y, "Flight Log Storage", 1, false, 2);
}
}
class BatteryVoltage extends AltosUIVoltageIndicator {
public double voltage(AltosState state) {
return state.battery_voltage;
}
public double good() {
return AltosLib.ao_battery_good;
}
public BatteryVoltage(Container container, int y) {
super(container, y, "Battery Voltage", 2);
}
}
class ReceiverBattery extends AltosUIVoltageIndicator {
public double voltage(AltosState state) { return AltosLib.MISSING; }
public double good() { return AltosLib.ao_battery_good; }
public boolean hide(AltosState state, AltosListenerState listener_state, int i) {
return value(state, listener_state, i) == AltosLib.MISSING;
}
public double value(AltosState state, AltosListenerState listener_state, int i) {
if (listener_state == null)
return AltosLib.MISSING;
return listener_state.battery;
}
public ReceiverBattery (AltosUIFlightTab container, int y) {
super(container, y, "Receiver Battery", 2);
}
}
public void labels(Container container, int y) {
GridBagLayout layout = (GridBagLayout)(container.getLayout());
GridBagConstraints c;
cur = new JLabel("Current");
cur.setFont(AltosUILib.label_font);
c = new GridBagConstraints();
c.gridx = 2; c.gridy = y;
c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
layout.setConstraints(cur, c);
add(cur);
max = new JLabel("Maximum");
max.setFont(AltosUILib.label_font);
c.gridx = 3; c.gridy = y;
layout.setConstraints(max, c);
add(max);
}
public void font_size_changed(int font_size) {
cur.setFont(AltosUILib.label_font);
max.setFont(AltosUILib.label_font);
super.font_size_changed(font_size);
}
public String getName() {
return "Status";
}
public TeleGPSState() {
int y = 0;
labels(this, y++);
add(new Height(this, y++));
add(new Speed(this, y++));
add(new Distance(this, y++));
add(new Range(this, y++));
add(new Bearing(this, y++));
add(new Elevation(this, y++));
add(new FirmwareVersion(this, y++));
add(new FlightLogMax(this, y++));
add(new BatteryVoltage(this, y++));
add(new ReceiverBattery(this, y++));
}
}

281
telegps/TeleGPSStatus.java Normal file
View File

@@ -0,0 +1,281 @@
/*
* 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.telegps;
import java.awt.*;
import javax.swing.*;
import org.altusmetrum.altoslib_14.*;
import org.altusmetrum.altosuilib_14.*;
public class TeleGPSStatus extends JComponent implements AltosFlightDisplay {
GridBagLayout layout;
public class Value {
JLabel label;
JTextField value;
void show(AltosState state, AltosListenerState listener_state) {}
void reset() {
value.setText("");
}
void set_font() {
label.setFont(AltosUILib.status_font);
value.setFont(AltosUILib.status_font);
}
void setVisible(boolean visible) {
label.setVisible(visible);
value.setVisible(visible);
}
public Value (GridBagLayout layout, int x, String text) {
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets(5, 5, 5, 5);
c.anchor = GridBagConstraints.CENTER;
c.fill = GridBagConstraints.BOTH;
c.weightx = 1;
c.weighty = 1;
label = new JLabel(text);
label.setFont(AltosUILib.status_font);
label.setHorizontalAlignment(SwingConstants.CENTER);
c.gridx = x; c.gridy = 0;
layout.setConstraints(label, c);
add(label);
value = new JTextField("");
value.setEditable(false);
value.setFont(AltosUILib.status_font);
value.setHorizontalAlignment(SwingConstants.CENTER);
c.gridx = x; c.gridy = 1;
layout.setConstraints(value, c);
add(value);
}
}
class Call extends Value {
String call;
void show(AltosState state, AltosListenerState listener_state) {
AltosCalData cal_data = state.cal_data();
if (cal_data == null)
System.out.printf("null cal data?\n");
if (cal_data.callsign != call) {
value.setText(cal_data.callsign);
call = cal_data.callsign;
}
if (cal_data.callsign == null)
setVisible(false);
else
setVisible(true);
}
public void reset() {
super.reset();
call = "";
}
public Call (GridBagLayout layout, int x) {
super (layout, x, "Callsign");
}
}
Call call;
class Serial extends Value {
int serial = -1;
void show(AltosState state, AltosListenerState listener_state) {
AltosCalData cal_data = state.cal_data();
if (cal_data.serial != serial) {
if (cal_data.serial == AltosLib.MISSING)
value.setText("none");
else
value.setText(String.format("%d", cal_data.serial));
serial = cal_data.serial;
}
}
public void reset() {
super.reset();
serial = -1;
}
public Serial (GridBagLayout layout, int x) {
super (layout, x, "Serial");
}
}
Serial serial;
class Flight extends Value {
int last_flight = -1;
void show(AltosState state, AltosListenerState listener_state) {
AltosCalData cal_data = state.cal_data();
if (cal_data.flight != last_flight) {
if (cal_data.flight == AltosLib.MISSING)
value.setText("none");
else
value.setText(String.format("%d", cal_data.flight));
last_flight = cal_data.flight;
}
}
public void reset() {
super.reset();
last_flight = -1;
}
public Flight (GridBagLayout layout, int x) {
super (layout, x, "Flight");
}
}
Flight flight;
class RSSI extends Value {
int rssi = 10000;
void show(AltosState state, AltosListenerState listener_state) {
int new_rssi = state.rssi();
if (new_rssi != rssi) {
value.setText(String.format("%d", new_rssi));
if (state.rssi == AltosLib.MISSING)
setVisible(false);
else
setVisible(true);
rssi = new_rssi;
}
}
public void reset() {
super.reset();
rssi = 10000;
}
public RSSI (GridBagLayout layout, int x) {
super (layout, x, "RSSI");
}
}
RSSI rssi;
class LastPacket extends Value {
long last_secs = -1;
void show(AltosState state, AltosListenerState listener_state) {
if (listener_state.running) {
long secs = (System.currentTimeMillis() - state.received_time + 500) / 1000;
if (secs != last_secs) {
value.setText(String.format("%d", secs));
last_secs = secs;
}
} else {
value.setText("done");
}
}
void reset() {
super.reset();
last_secs = -1;
}
void disable() {
value.setText("");
}
public LastPacket(GridBagLayout layout, int x) {
super (layout, x, "Age");
}
}
LastPacket last_packet;
public void disable_receive() {
last_packet.disable();
}
public void reset () {
call.reset();
serial.reset();
flight.reset();
rssi.reset();
last_packet.reset();
}
public void font_size_changed(int font_size) {
call.set_font();
serial.set_font();
flight.set_font();
rssi.set_font();
last_packet.set_font();
}
public void units_changed(boolean imperial_units) {
}
public void show (AltosState state, AltosListenerState listener_state) {
call.show(state, listener_state);
serial.show(state, listener_state);
flight.show(state, listener_state);
rssi.show(state, listener_state);
last_packet.show(state, listener_state);
if (!listener_state.running)
stop();
}
public int height() {
Dimension d = layout.preferredLayoutSize(this);
return d.height;
}
TeleGPSStatusUpdate status_update;
javax.swing.Timer timer;
public void start(TeleGPSStatusUpdate status_update) {
this.status_update = status_update;
timer = new javax.swing.Timer(100, status_update);
timer.start();
}
public void stop() {
if (timer != null) {
timer.stop();
timer = null;
}
}
public TeleGPSStatus() {
layout = new GridBagLayout();
setLayout(layout);
call = new Call(layout, 0);
serial = new Serial(layout, 1);
flight = new Flight(layout, 2);
rssi = new RSSI(layout, 4);
last_packet = new LastPacket(layout, 5);
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright © 2012 Keith Packard <keithp@keithp.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
package org.altusmetrum.telegps;
import java.awt.event.*;
import org.altusmetrum.altoslib_14.*;
public class TeleGPSStatusUpdate implements ActionListener {
public AltosState saved_state;
public AltosListenerState saved_listener_state;
TeleGPSStatus status;
public void actionPerformed (ActionEvent e) {
if (saved_state != null) {
if (saved_listener_state == null)
saved_listener_state = new AltosListenerState();
status.show(saved_state, saved_listener_state);
}
}
public TeleGPSStatusUpdate (TeleGPSStatus in_status) {
status = in_status;
}
}

View File

@@ -0,0 +1,11 @@
[Desktop Entry]
Type=Application
Name=TeleGPS
GenericName=TeleGPS monitor, download and analysis
Comment=View and log data from TeleGPS tracking devices
Icon=%icondir%/altusmetrum-telegps.svg
Exec=%bindir%/telegps %F
Terminal=false
MimeType=application/vnd.altusmetrum.telemetry;application/vnd.altusmetrum.eeprom
Categories=Education;Electronics;Science;
Keywords=Telemetry;GPS

7
telegps/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](/TeleGPS/releases/%version%/TeleGPS-Windows-%version_dash%.exe)
- [Mac OS X Package](/TeleGPS/releases/%version%/TeleGPS-Mac-%version%.dmg)
- [Linux](/TeleGPS/releases/%version%/TeleGPS-Linux-%version%.sh)
- [Source Snapshot](http://git.gag.com/?p=fw/altos;a=snapshot;h=refs/tags/%version%;sf=tgz)

4
telegps/telegps-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"/telegps-fat.jar "$@"

View File

@@ -0,0 +1,241 @@
!addplugindir ../altosui/Instdrv/NSIS/Plugins
!addincludedir ../altosui/Instdrv/NSIS/Includes
!include x64.nsh
!include java.nsh
!include refresh-sh.nsh
!define REG_NAME "TeleGPS"
!define PROG_ID_TELEM "altusmetrum.telegps.telem.1"
!define PROG_ID_EEPROM "altusmetrum.telegps.eeprom.1"
!define FAT_NAME "telegps-fat.jar"
!define WIN_APP_ICON "altusmetrum-telegps.ico"
!define WIN_APP_EXE "altusmetrum-telegps.exe"
!define WIN_TELEM_EXE "application-vnd.altusmetrum.telemetry.exe"
!define WIN_EEPROM_EXE "application-vnd.altusmetrum.eeprom.exe"
Name "${REG_NAME} Installer"
; Default install directory
InstallDir "$PROGRAMFILES\AltusMetrum"
; Tell the installer where to re-install a new version
InstallDirRegKey HKLM "Software\${REG_NAME}" "Install_Dir"
LicenseText "GNU General Public License Version 2"
LicenseData "../COPYING"
; Need admin privs for Vista or Win7
RequestExecutionLevel admin
ShowInstDetails Show
ComponentText "${REG_NAME} Software and Driver Installer"
Function .onInit
DetailPrint "Checking host operating system"
${If} ${RunningX64}
DetailPrint "Installer running on 64-bit host"
SetRegView 64
StrCpy $INSTDIR "$PROGRAMFILES64\AltusMetrum"
${DisableX64FSRedirection}
${EndIf}
FunctionEnd
Function un.onInit
DetailPrint "Checking host operating system"
${If} ${RunningX64}
DetailPrint "Installer running on 64-bit host"
SetRegView 64
StrCpy $INSTDIR "$PROGRAMFILES64\AltusMetrum"
${DisableX64FSRedirection}
${EndIf}
FunctionEnd
; Pages to present
Page license
Page components
Page directory
Page instfiles
UninstPage uninstConfirm
UninstPage instfiles
; And the stuff to install
Section "Install Driver" InstDriver
InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} AltusMetrumSerial
Pop $0
DetailPrint "InitDriverSetup: $0"
InstDrv::DeleteOemInfFiles /NOUNLOAD
InstDrv::CreateDevice /NOUNLOAD
SetOutPath $INSTDIR
File "../altusmetrum.inf"
File "../altusmetrum.cat"
${DisableX64FSRedirection}
IfFileExists $WINDIR\System32\PnPutil.exe 0 nopnp
${DisableX64FSRedirection}
nsExec::ExecToLog '"$WINDIR\System32\PnPutil.exe" -i -a "$INSTDIR\altusmetrum.inf"'
Goto done
nopnp:
InstDrv::InstallDriver /NOUNLOAD "$INSTDIR\altusmetrum.inf"
done:
SectionEnd
Section "${REG_NAME} Application"
Call DetectJRE
SetOutPath $INSTDIR
File "${FAT_NAME}"
File "altoslib_@ALTOSLIB_VERSION@.jar"
File "altosuilib_@ALTOSUILIB_VERSION@.jar"
File "cmudict04.jar"
File "cmulex.jar"
File "cmu_time_awb.jar"
File "cmutimelex.jar"
File "cmu_us_kal.jar"
File "en_us.jar"
File "freetts.jar"
File "jfreechart.jar"
File "jcommon.jar"
File "../icon/${WIN_APP_EXE}"
File "*.dll"
File "../icon/${WIN_APP_ICON}"
CreateShortCut "$SMPROGRAMS\${REG_NAME}.lnk" "$INSTDIR\${WIN_APP_EXE}" "" "$INSTDIR\${WIN_APP_ICON}"
SectionEnd
Section "${REG_NAME} Desktop Shortcut"
CreateShortCut "$DESKTOP\${REG_NAME}.lnk" "$INSTDIR\${WIN_APP_EXE}" "" "$INSTDIR\${WIN_APP_ICON}"
SectionEnd
Section "TeleGPS, TeleDongle and TeleBT Firmware"
SetOutPath $INSTDIR
File "../src/telegps-v1.0/telegps-v1.0-${VERSION}.ihx"
File "../src/telegps-v2.0/telegps-v2.0-${VERSION}.ihx"
File "../src/telegps-v3.0/telegps-v3.0-${VERSION}.ihx"
File "../src/teledongle-v3.0/teledongle-v3.0-${VERSION}.ihx"
File "../src/telebt-v3.0/telebt-v3.0-${VERSION}.ihx"
File "../src/telebt-v4.0/telebt-v4.0-${VERSION}.ihx"
SectionEnd
Section "Documentation"
SetOutPath $INSTDIR
File "../doc/telegps.pdf"
File "../doc/altos.pdf"
File "../doc/telemetry.pdf"
SectionEnd
Section "File Associations"
${DisableX64FSRedirection}
SetOutPath $INSTDIR
File "../icon/${WIN_TELEM_EXE}"
File "../icon/${WIN_EEPROM_EXE}"
DeleteRegKey HKCR "${PROG_ID_TELEM}"
DeleteRegKey HKCR "${PROG_ID_EEPROM}"
DeleteRegKey HKCR ".eeprom\${PROG_ID_EEPROM}"
DeleteRegValue HKCR ".eeprom\OpenWithProgids" "${PROG_ID_EEPROM}"
DeleteRegKey HKCR ".telem\${PROG_ID_EEPROM}"
DeleteRegValue HKCR ".telem\OpenWithProgids" "${PROG_ID_EEPROM}"
; .eeprom elements
WriteRegStr HKCR "${PROG_ID_EEPROM}" "" "Altus Metrum Log File"
WriteRegStr HKCR "${PROG_ID_EEPROM}" "FriendlyTypeName" "Altus Metrum Log File"
WriteRegStr HKCR "${PROG_ID_EEPROM}\CurVer" "" "${PROG_ID_EEPROM}"
WriteRegStr HKCR "${PROG_ID_EEPROM}\DefaultIcon" "" '"$INSTDIR\${WIN_EEPROM_EXE}",-101'
WriteRegExpandStr HKCR "${PROG_ID_EEPROM}\shell\open\command" "" '"$INSTDIR\${WIN_APP_EXE}" "%1"'
WriteRegStr HKCR ".eeprom" "" "${PROG_ID_EEPROM}"
WriteRegStr HKCR ".eeprom" "PerceivedType" "Altus Metrum Log File"
WriteRegStr HKCR ".eeprom" "Content Type" "application/vnd.altusmetrum.eeprom"
WriteRegStr HKCR ".eeprom\OpenWithProgids" "${PROG_ID_EEPROM}" ""
WriteRegStr HKCR ".eeprom\${PROG_ID_EEPROM}" "" "${REG_NAME}"
; .telem elements
WriteRegStr HKCR "${PROG_ID_TELEM}" "" "Altus Metrum Telemetry File"
WriteRegStr HKCR "${PROG_ID_TELEM}" "FriendlyTypeName" "Altus Metrum Telemetry File"
WriteRegStr HKCR "${PROG_ID_TELEM}\CurVer" "" "${PROG_ID_TELEM}"
WriteRegStr HKCR "${PROG_ID_TELEM}\DefaultIcon" "" '"$INSTDIR\${WIN_TELEM_EXE}",-101'
WriteRegExpandStr HKCR "${PROG_ID_TELEM}\shell\open\command" "" '"$INSTDIR\${WIN_APP_EXE}" "%1"'
WriteRegStr HKCR ".telem" "" "${PROG_ID_TELEM}"
WriteRegStr HKCR ".telem" "PerceivedType" "Altus Metrum Telemetry File"
WriteRegStr HKCR ".telem" "Content Type" "application/vnd.altusmetrum.telemetry"
WriteRegStr HKCR ".telem\OpenWithProgids" "${PROG_ID_TELEM}" ""
WriteRegStr HKCR ".telem\${PROG_ID_TELEM}" "" "${REG_NAME}"
Call RefreshShellIcons
SectionEnd
Section "Uninstaller"
; Deal with the uninstaller
${DisableX64FSRedirection}
SetOutPath $INSTDIR
; Write the install path to the registry
WriteRegStr HKLM "SOFTWARE\${REG_NAME}" "Install_Dir" "$INSTDIR"
; Write the uninstall keys for windows
WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "DisplayName" "${REG_NAME}"
WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "UninstallString" '"$INSTDIR\uninstall-${REG_NAME}.exe"'
WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "NoModify" "1"
WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "NoRepair" "1"
WriteUninstaller "uninstall-${REG_NAME}.exe"
SectionEnd
Section "Uninstall"
${DisableX64FSRedirection}
DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}"
DeleteRegKey HKLM "SOFTWARE\${REG_NAME}"
DetailPrint "Delete uninstall reg entries"
DeleteRegKey HKCR "${PROG_ID_EEPROM}"
DeleteRegKey HKCR "${PROG_ID_TELEM}"
DeleteRegKey HKCR ".eeprom\${PROG_ID_EEPROM}"
DeleteRegValue HKCR ".eeprom\OpenWithProgids" "${PROG_ID_EEPROM}"
DeleteRegKey HKCR ".telem\${PROG_ID_TELEM}"
DeleteRegValue HKCR ".telem\OpenWithProgids" "${PROG_ID_TELEM}"
DetailPrint "Delete file association reg entries"
Delete "$INSTDIR\${FAT_NAME}"
Delete "$INSTDIR\uninstall-${REG_NAME}.exe"
Delete "$INSTDIR\${WIN_APP_ICON}"
Delete "$INSTDIR\${WIN_APP_EXE}"
; Remove shortcuts, if any
Delete "$SMPROGRAMS\${REG_NAME}.lnk"
Delete "$DESKTOP\${REG_NAME}.lnk"
Call un.RefreshShellIcons
SectionEnd

46
telegps/telegps.1 Normal file
View File

@@ -0,0 +1,46 @@
.\"
.\" Copyright © 2010 Bdale Garbee <bdale@gag.com>
.\"
.\" This program is free software; you can redistribute it and/or modify
.\" it under the terms of the GNU General Public License as published by
.\" the Free Software Foundation; either version 2 of the License, or
.\" (at your option) any later version.
.\"
.\" This program is distributed in the hope that it will be useful, but
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
.\" General Public License for more details.
.\"
.\" You should have received a copy of the GNU General Public License along
.\" with this program; if not, write to the Free Software Foundation, Inc.,
.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
.\"
.\"
.TH ALTOSUI 1 "altosui" ""
.SH NAME
altosui \- Rocket flight monitor
.SH SYNOPSIS
.B "altosui"
.SH DESCRIPTION
.I altosui
connects to a TeleDongle or TeleMetrum device through a USB serial device.
It provides a menu-oriented
user interface to monitor, record and review rocket flight data.
.SH USAGE
When connected to a TeleDongle device, altosui turns on the radio
receiver and listens for telemetry packets. It displays the received
telemetry data, and reports flight status via voice synthesis. All
received telemetry information is recorded to a file.
.P
When connected to a TeleMetrum device, altosui can be used to configure the
TeleMetrum, and to downloads the eeprom data and store it in a file.
.P
A number of other menu options exist, including the ability to export flight
data in different formats.
.SH FILES
All data log files are recorded into a user-specified directory
(default ~/TeleMetrum). Files are named using the current date, the serial
number of the reporting device, the flight number recorded in the data
and either '.telem' for telemetry data or '.eeprom' for eeprom data.
.SH AUTHOR
Keith Packard