This commit is contained in:
Andrea Cavalli 2022-03-14 11:22:38 +01:00
parent 12329c5ffe
commit 1ec7bee089
30 changed files with 771 additions and 1454 deletions

View File

@ -45,6 +45,11 @@
<artifactId>junit-jupiter</artifactId> <artifactId>junit-jupiter</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>com.flowpowered</groupId>
<artifactId>flow-nbt</artifactId>
<version>1.0.1-SNAPSHOT</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -3,11 +3,9 @@ package it.cavallium.warppi;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.util.List; import java.util.List;
import java.util.Map;
import it.cavallium.warppi.boot.StartupArguments; import it.cavallium.warppi.boot.StartupArguments;
import it.cavallium.warppi.device.DeviceStateDevice; import it.cavallium.warppi.device.DeviceStateDevice;
@ -23,7 +21,7 @@ public interface Platform {
Gpio getGpio(); Gpio getGpio();
StorageUtils getStorageUtils(); PlatformStorage getPlatformStorage();
ImageUtils getImageUtils(); ImageUtils getImageUtils();
@ -76,7 +74,7 @@ public interface Platform {
* *
* @return a <code>List</code> of paths of files which contain DSL rules. * @return a <code>List</code> of paths of files which contain DSL rules.
* Each <code>String</code> in the returned <code>List</code> can be passed as an argument to * Each <code>String</code> in the returned <code>List</code> can be passed as an argument to
* {@link StorageUtils#getResourceStream(String)} to access the corresponding file's contents. * {@link PlatformStorage#getResourceStream(String)} to access the corresponding file's contents.
* @throws IOException if an IO error occurs while getting the list of rule file paths. * @throws IOException if an IO error occurs while getting the list of rule file paths.
*/ */
List<String> getRuleFilePaths() throws IOException; List<String> getRuleFilePaths() throws IOException;
@ -135,7 +133,7 @@ public interface Platform {
} }
} }
public interface StorageUtils { public interface PlatformStorage {
int OpenOptionWrite = 0; int OpenOptionWrite = 0;
int OpenOptionCreate = 1; int OpenOptionCreate = 1;
@ -170,7 +168,7 @@ public interface Platform {
List<String> readAllLines(InputStream input) throws IOException; List<String> readAllLines(InputStream input) throws IOException;
String getBasePath(); File getRootPath();
} }
public interface Semaphore { public interface Semaphore {

View File

@ -25,7 +25,7 @@ public abstract class PngSkin implements Skin {
if (!file.startsWith("/")) { if (!file.startsWith("/")) {
file = "/" + file; file = "/" + file;
} }
final ImageReader r = WarpPI.getPlatform().getImageUtils().load(WarpPI.getPlatform().getStorageUtils().getResourceStream(file)); final ImageReader r = WarpPI.getPlatform().getImageUtils().load(WarpPI.getPlatform().getPlatformStorage().getResourceStream(file));
if (r == null) { if (r == null) {
skinData = new int[0]; skinData = new int[0];
skinSize = new int[] { 0, 0 }; skinSize = new int[] { 0, 0 };

View File

@ -1,12 +1,8 @@
package it.cavallium.warppi.gui.graphicengine.impl.common; package it.cavallium.warppi.gui.graphicengine.impl.common;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
import it.cavallium.warppi.WarpPI; import it.cavallium.warppi.WarpPI;
import it.cavallium.warppi.Platform.ConsoleUtils; import it.cavallium.warppi.Platform.ConsoleUtils;
@ -101,7 +97,7 @@ public abstract class RFTFont implements BinaryFont {
if (!string.startsWith("/")) { if (!string.startsWith("/")) {
string = "/" + string; string = "/" + string;
} }
InputStream res = WarpPI.getPlatform().getStorageUtils().getResourceStream(string); InputStream res = WarpPI.getPlatform().getPlatformStorage().getResourceStream(string);
final int[] file = Utils.realBytes(Utils.convertStreamToByteArray(res, res.available())); final int[] file = Utils.realBytes(Utils.convertStreamToByteArray(res, res.available()));
final int filelength = file.length; final int filelength = file.length;
if (filelength >= 16) { if (filelength >= 16) {

View File

@ -80,8 +80,8 @@ public class RulesManager {
); );
final String source; final String source;
try (final InputStream resource = platform.getStorageUtils().getResourceStream(path)) { try (final InputStream resource = platform.getPlatformStorage().getResourceStream(path)) {
source = platform.getStorageUtils().read(resource); source = platform.getPlatformStorage().read(resource);
} }
try { try {

View File

@ -578,7 +578,7 @@ public class Utils {
public static InputStream getResourceStreamSafe(final String string) throws IOException, URISyntaxException { public static InputStream getResourceStreamSafe(final String string) throws IOException, URISyntaxException {
try { try {
return WarpPI.getPlatform().getStorageUtils().getResourceStream(string); return WarpPI.getPlatform().getPlatformStorage().getResourceStream(string);
} catch (final Exception ex) { } catch (final Exception ex) {
return null; return null;
} }

View File

@ -11,7 +11,6 @@ import java.util.function.Consumer;
import it.cavallium.warppi.event.TouchEvent; import it.cavallium.warppi.event.TouchEvent;
import it.cavallium.warppi.gui.graphicengine.impl.jogl.JOGLDisplayOutputDevice; import it.cavallium.warppi.gui.graphicengine.impl.jogl.JOGLDisplayOutputDevice;
import it.cavallium.warppi.gui.graphicengine.impl.jogl.JOGLEngine;
import it.cavallium.warppi.gui.graphicengine.impl.swing.SwingDeviceState; import it.cavallium.warppi.gui.graphicengine.impl.swing.SwingDeviceState;
import it.cavallium.warppi.gui.graphicengine.impl.swing.SwingTouchInputDevice; import it.cavallium.warppi.gui.graphicengine.impl.swing.SwingTouchInputDevice;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
@ -35,7 +34,7 @@ public class DesktopPlatform implements Platform {
private final DesktopConsoleUtils cu; private final DesktopConsoleUtils cu;
private final DesktopGpio gi; private final DesktopGpio gi;
private final DesktopStorageUtils su; private final DesktopPlatformStorage su;
private final ImageUtils pu; private final ImageUtils pu;
private final String on; private final String on;
private final DesktopSettings settings; private final DesktopSettings settings;
@ -49,7 +48,7 @@ public class DesktopPlatform implements Platform {
public DesktopPlatform() { public DesktopPlatform() {
cu = new DesktopConsoleUtils(); cu = new DesktopConsoleUtils();
gi = new DesktopGpio(); gi = new DesktopGpio();
su = new DesktopStorageUtils(); su = new DesktopPlatformStorage();
pu = new DesktopImageUtils(); pu = new DesktopImageUtils();
on = System.getProperty("os.name").toLowerCase(); on = System.getProperty("os.name").toLowerCase();
settings = new DesktopSettings(); settings = new DesktopSettings();
@ -66,7 +65,7 @@ public class DesktopPlatform implements Platform {
} }
@Override @Override
public StorageUtils getStorageUtils() { public PlatformStorage getPlatformStorage() {
return su; return su;
} }
@ -159,10 +158,10 @@ public class DesktopPlatform implements Platform {
@Override @Override
public List<String> getRuleFilePaths() throws IOException { public List<String> getRuleFilePaths() throws IOException {
final File dslRulesPath = getStorageUtils().get("rules/"); final File dslRulesPath = getPlatformStorage().get("rules/");
List<String> paths = new ArrayList<>(); List<String> paths = new ArrayList<>();
if (dslRulesPath.exists()) { if (dslRulesPath.exists()) {
for (final File file : getStorageUtils().walk(dslRulesPath)) { for (final File file : getPlatformStorage().walk(dslRulesPath)) {
final String path = file.toString(); final String path = file.toString();
if (path.endsWith(".rules")) { if (path.endsWith(".rules")) {
paths.add(path); paths.add(path);

View File

@ -26,10 +26,10 @@ import java.util.stream.Stream;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import it.cavallium.warppi.Platform.StorageUtils; import it.cavallium.warppi.Platform.PlatformStorage;
import it.cavallium.warppi.util.ClassUtils; import it.cavallium.warppi.util.ClassUtils;
public class DesktopStorageUtils implements StorageUtils { public class DesktopPlatformStorage implements PlatformStorage {
@Override @Override
public boolean exists(final File f) { public boolean exists(final File f) {
return f.exists(); return f.exists();
@ -188,11 +188,11 @@ public class DesktopStorageUtils implements StorageUtils {
int i = 0; int i = 0;
for (final int opt : options) { for (final int opt : options) {
switch (opt) { switch (opt) {
case StorageUtils.OpenOptionCreate: { case PlatformStorage.OpenOptionCreate: {
noptions[i] = StandardOpenOption.CREATE; noptions[i] = StandardOpenOption.CREATE;
break; break;
} }
case StorageUtils.OpenOptionWrite: { case PlatformStorage.OpenOptionWrite: {
noptions[i] = StandardOpenOption.WRITE; noptions[i] = StandardOpenOption.WRITE;
break; break;
} }
@ -213,7 +213,7 @@ public class DesktopStorageUtils implements StorageUtils {
} }
@Override @Override
public String getBasePath() { public File getRootPath() {
return ""; return new File("");
} }
} }

View File

@ -205,7 +205,7 @@ public class SwingWindow extends JFrame {
} }
private void createBtn(final int row, final int col) throws IOException, URISyntaxException { private void createBtn(final int row, final int col) throws IOException, URISyntaxException {
final BufferedImage img = ImageIO.read(WarpPI.getPlatform().getStorageUtils().getResourceStream("/desktop-buttons.png")); final BufferedImage img = ImageIO.read(WarpPI.getPlatform().getPlatformStorage().getResourceStream("/desktop-buttons.png"));
final SwingAdvancedButton b = new SwingAdvancedButton(img, new Dimension((int) (BTN_SIZE * 1.5), BTN_SIZE)); final SwingAdvancedButton b = new SwingAdvancedButton(img, new Dimension((int) (BTN_SIZE * 1.5), BTN_SIZE));
b.drawDefaultComponent = false; b.drawDefaultComponent = false;
b.setText(Keyboard.getKeyName(row, col)); b.setText(Keyboard.getKeyName(row, col));

View File

@ -1,7 +1,6 @@
package it.cavallium.warppi.gui.graphicengine.impl.jogl; package it.cavallium.warppi.gui.graphicengine.impl.jogl;
import java.io.IOException; import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
@ -30,7 +29,7 @@ public class JOGLSkin implements Skin {
@Override @Override
public void load(final String file) throws IOException { public void load(final String file) throws IOException {
final boolean isResource = !Files.exists(Paths.get(file)); final boolean isResource = !Files.exists(Paths.get(file));
if (isResource && WarpPI.getPlatform().getStorageUtils().getResourceStream(file) == null) if (isResource && WarpPI.getPlatform().getPlatformStorage().getResourceStream(file) == null)
throw new IOException("File '" + file + "' not found!"); throw new IOException("File '" + file + "' not found!");
texturePath = file; texturePath = file;
this.isResource = isResource; this.isResource = isResource;

View File

@ -1,150 +0,0 @@
/*
* Class NativeUtils is published under the The MIT License:
*
* Copyright (c) 2012 Adam Heinrich <adam@adamh.cz>
*
* 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.
*/
package cz.adamh.utils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileSystemNotFoundException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.ProviderNotFoundException;
import java.nio.file.StandardCopyOption;
/**
* A simple library class which helps with loading dynamic libraries stored in
* the
* JAR archive. These libraries usualy contain implementation of some methods in
* native code (using JNI - Java Native Interface).
*
* @see http://adamheinrich.com/blog/2012/how-to-load-native-jni-library-from-jar
* @see https://github.com/adamheinrich/native-utils
*
*/
public class NativeUtils {
/**
* The minimum length a prefix for a file has to have according to
* {@link File#createTempFile(String, String)}}.
*/
private static final int MIN_PREFIX_LENGTH = 3;
/**
* Temporary directory which will contain the DLLs.
*/
private static File temporaryDir;
/**
* Private constructor - this class will never be instanced
*/
private NativeUtils() {}
/**
* Loads library from current JAR archive
*
* The file from JAR is copied into system temporary directory and then
* loaded. The temporary file is deleted after
* exiting.
* Method uses String as filename because the pathname is "abstract", not
* system-dependent.
*
* @param path
* The path of file inside JAR as absolute path (beginning with
* '/'), e.g. /package/File.ext
* @throws IOException
* If temporary file creation or read/write operation fails
* @throws IllegalArgumentException
* If source file (param path) does not exist
* @throws IllegalArgumentException
* If the path is not absolute or if the filename is shorter
* than three characters
* (restriction of
* {@link File#createTempFile(java.lang.String, java.lang.String)}).
* @throws FileNotFoundException
* If the file could not be found inside the JAR.
*/
public static void loadLibraryFromJar(final String path) throws IOException {
if (!path.startsWith("/"))
throw new IllegalArgumentException("The path has to be absolute (start with '/').");
// Obtain filename from path
final String[] parts = path.split("/");
final String filename = parts.length > 1 ? parts[parts.length - 1] : null;
// Check if the filename is okay
if (filename == null || filename.length() < NativeUtils.MIN_PREFIX_LENGTH)
throw new IllegalArgumentException("The filename has to be at least 3 characters long.");
// Prepare temporary file
if (NativeUtils.temporaryDir == null) {
NativeUtils.temporaryDir = NativeUtils.createTempDirectory("nativeutils");
NativeUtils.temporaryDir.deleteOnExit();
}
final File temp = new File(NativeUtils.temporaryDir, filename);
try (InputStream is = NativeUtils.class.getResourceAsStream(path)) {
Files.copy(is, temp.toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch (final IOException e) {
temp.delete();
throw e;
} catch (final NullPointerException e) {
temp.delete();
throw new FileNotFoundException("File " + path + " was not found inside JAR.");
}
try {
System.load(temp.getAbsolutePath());
} finally {
if (NativeUtils.isPosixCompliant())
// Assume POSIX compliant file system, can be deleted after loading
temp.delete();
else
// Assume non-POSIX, and don't delete until last file descriptor closed
temp.deleteOnExit();
}
}
private static boolean isPosixCompliant() {
try {
if (FileSystems.getDefault().supportedFileAttributeViews().contains("posix"))
return true;
return false;
} catch (FileSystemNotFoundException | ProviderNotFoundException | SecurityException e) {
return false;
}
}
private static File createTempDirectory(final String prefix) throws IOException {
final String tempDir = System.getProperty("java.io.tmpdir");
final File generatedDir = new File(tempDir, prefix + System.nanoTime());
if (!generatedDir.mkdir())
throw new IOException("Failed to create temp directory " + generatedDir.getName());
return generatedDir;
}
}

View File

@ -1,33 +0,0 @@
package it.cavallium.warppi;
import java.nio.ByteBuffer;
public class MmapByteBuffer {
private final int fd;
private final int address;
private final int length;
private final ByteBuffer buffer;
public MmapByteBuffer(final int fd, final int address, final int length, final ByteBuffer buffer) {
this.fd = fd;
this.address = address;
this.length = length;
this.buffer = buffer;
}
public int getFd() {
return fd;
}
public int getAddress() {
return address;
}
public int getLength() {
return length;
}
public ByteBuffer getBuffer() {
return buffer;
}
}

View File

@ -1,23 +0,0 @@
package it.cavallium.warppi;
public class TestJNI {
public TestJNI() {
}
static {
System.load("/boot/libpicalc.so");
}
private native MmapByteBuffer getDisplayBuffer();
private native void disposeDisplayBuffer();
public MmapByteBuffer retrieveBuffer() {
return getDisplayBuffer();
}
public void deleteBuffer() {
disposeDisplayBuffer();
}
}

View File

@ -1,191 +0,0 @@
package it.cavallium.warppi.gui.graphicengine.impl.framebuffer;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.util.concurrent.Semaphore;
import it.cavallium.warppi.MmapByteBuffer;
import it.cavallium.warppi.StaticVars;
import it.cavallium.warppi.TestJNI;
import it.cavallium.warppi.flow.BehaviorSubject;
import it.cavallium.warppi.flow.Observable;
import it.cavallium.warppi.gui.graphicengine.GraphicEngine;
import it.cavallium.warppi.gui.graphicengine.Renderer;
import it.cavallium.warppi.gui.graphicengine.RenderingLoop;
public class FBEngine implements GraphicEngine {
@SuppressWarnings("unused")
private static final int FB_DISPLAY_WIDTH = 320;
@SuppressWarnings("unused")
private static final int FB_DISPLAY_HEIGHT = 480;
@SuppressWarnings("unused")
private static final int FB_DISPLAY_BPP = 32;
private static final int WIDTH = 480;
private static final int HEIGHT = 320;
private static final int[] SIZE = new int[] { FBEngine.WIDTH, FBEngine.HEIGHT };
private BehaviorSubject<Integer[]> onResize;
private final TestJNI jni = new TestJNI();
public FBRenderer r;
private MappedByteBuffer fb;
MmapByteBuffer realFb;
private RandomAccessFile fbFileRW;
public volatile boolean initialized = false;
public Semaphore exitSemaphore = new Semaphore(0);
@Override
public int[] getSize() {
return FBEngine.SIZE;
}
@Override
public boolean isInitialized() {
return initialized;
}
@Override
public void setTitle(final String title) {}
@Override
public void setResizable(final boolean r) {}
@Override
public void setDisplayMode(final int ww, final int wh) {}
@Override
public void create(final Runnable onInitialized) {
onResize = BehaviorSubject.create(new Integer[] { FBEngine.SIZE[0], FBEngine.SIZE[1] });
realFb = jni.retrieveBuffer();
final long fbLen = realFb.getLength();
fb = (MappedByteBuffer) ByteBuffer.allocateDirect((int) fbLen);
r = new FBRenderer(this, fb);
initialized = true;
if (onInitialized != null)
onInitialized.run();
}
@Override
public Observable<Integer[]> onResize() {
return onResize;
}
@Override
public int getWidth() {
return FBEngine.WIDTH;
}
@Override
public int getHeight() {
return FBEngine.HEIGHT;
}
@Override
public void destroy() {
try {
fbFileRW.close();
} catch (final IOException e) {
e.printStackTrace();
}
}
@Override
public void start(final RenderingLoop d) {
final Thread th = new Thread(() -> {
try {
double extratime = 0;
while (initialized) {
final long start = System.currentTimeMillis();
d.refresh();
repaint();
final long end = System.currentTimeMillis();
final double delta = (end - start) / 1000d;
final int deltaInt = (int) Math.floor(delta);
final int extraTimeInt = (int) Math.floor(extratime);
if (extraTimeInt + deltaInt < 50) {
Thread.sleep(50 - (extraTimeInt + deltaInt));
extratime = 0;
} else
extratime += delta - 50d;
}
} catch (final InterruptedException e) {
e.printStackTrace();
}
});
th.setName("CPU rendering thread");
th.setDaemon(true);
th.start();
}
private int _________________TMP = 0;
@Override
public void repaint() {
if (_________________TMP % 100 == 0) {
System.out.println(System.currentTimeMillis());
_________________TMP = 0;
}
_________________TMP++;
realFb.getBuffer().clear();
realFb.getBuffer().put(fb);
for (int i = 0; i < fb.capacity() / 2; i++)
realFb.getBuffer().put(i, (byte) (_________________TMP < 50 ? 0xFF : 0xF0));
for (int i = fb.capacity() / 2; i < fb.capacity(); i++)
realFb.getBuffer().put(i, (byte) 0x18);
}
@Override
public Renderer getRenderer() {
return r;
}
@Override
public FBFont loadFont(final String fontName) throws IOException {
return new FBFont(fontName);
}
@Override
public FBFont loadFont(final String path, final String fontName) throws IOException {
return new FBFont(path, fontName);
}
@Override
public FBSkin loadSkin(final String file) throws IOException {
return new FBSkin(file);
}
@Override
public void waitForExit() {
try {
exitSemaphore.acquire();
} catch (final InterruptedException e) {}
}
@Override
public boolean isSupported() {
if (StaticVars.startupArguments.isEngineForced() && StaticVars.startupArguments.isFrameBufferEngineForced() == false)
return false;
/*
File fbFile = new File("/dev/fb1");
try {
fbFileRW = new RandomAccessFile(fbFile, "rw");
fbFileRW.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, fbFile.length());
fbFileRW.close();
return true;
} catch (IOException ex) {
System.err.println("Cannot read framebuffer fb1.");
ex.printStackTrace();
}
*/
return false;
}
@Override
public boolean doesRefreshPauses() {
return true;
}
}

View File

@ -1,25 +0,0 @@
package it.cavallium.warppi.gui.graphicengine.impl.framebuffer;
import java.io.IOException;
import it.cavallium.warppi.device.display.DisplayOutputDevice;
import it.cavallium.warppi.gui.graphicengine.impl.common.RFTFont;
public class FBFont extends RFTFont {
public FBFont(final String fontName) throws IOException {
super(fontName);
}
public FBFont(final String path, final String fontName) throws IOException {
super(path, fontName);
}
@Override
public void use(final DisplayOutputDevice d) {
@SuppressWarnings("unused")
final FBEngine dfb = (FBEngine) d;
// TODO: implement
}
}

View File

@ -1,139 +0,0 @@
package it.cavallium.warppi.gui.graphicengine.impl.framebuffer;
import java.nio.MappedByteBuffer;
import it.cavallium.warppi.gui.graphicengine.BinaryFont;
import it.cavallium.warppi.gui.graphicengine.Renderer;
public class FBRenderer implements Renderer {
public FBRenderer(final FBEngine fbEngine, final MappedByteBuffer fb) {}
@Override
public void glColor3i(final int r, final int gg, final int b) {
// TODO Auto-generated method stub
}
@Override
public void glColor(final int c) {
// TODO Auto-generated method stub
}
@Override
public void glColor4i(final int red, final int green, final int blue, final int alpha) {
// TODO Auto-generated method stub
}
@Override
public void glColor3f(final float red, final float green, final float blue) {
// TODO Auto-generated method stub
}
@Override
public void glColor4f(final float red, final float green, final float blue, final float alpha) {
// TODO Auto-generated method stub
}
@Override
public void glClearColor4i(final int red, final int green, final int blue, final int alpha) {
// TODO Auto-generated method stub
}
@Override
public void glClearColor4f(final float red, final float green, final float blue, final float alpha) {
// TODO Auto-generated method stub
}
@Override
public int glGetClearColor() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void glClearColor(final int c) {
// TODO Auto-generated method stub
}
@Override
public void glClear(final int screenWidth, final int screenHeight) {
// TODO Auto-generated method stub
}
@Override
public void glDrawLine(final float x0, final float y0, final float x1, final float y1) {
// TODO Auto-generated method stub
}
@Override
public void glFillRect(final float x, final float y, final float width, final float height, final float uvX,
final float uvY, final float uvWidth, final float uvHeight) {
// TODO Auto-generated method stub
}
@Override
public void glFillColor(final float x, final float y, final float width, final float height) {
// TODO Auto-generated method stub
}
@Override
public void glDrawCharLeft(final int x, final int y, final char ch) {
// TODO Auto-generated method stub
}
@Override
public void glDrawCharCenter(final int x, final int y, final char ch) {
// TODO Auto-generated method stub
}
@Override
public void glDrawCharRight(final int x, final int y, final char ch) {
// TODO Auto-generated method stub
}
@Override
public void glDrawStringLeft(final float x, final float y, final String text) {
// TODO Auto-generated method stub
}
@Override
public void glDrawStringCenter(final float x, final float y, final String text) {
// TODO Auto-generated method stub
}
@Override
public void glDrawStringRight(final float x, final float y, final String text) {
// TODO Auto-generated method stub
}
@Override
public void glClearSkin() {
// TODO Auto-generated method stub
}
@Override
public BinaryFont getCurrentFont() {
// TODO Auto-generated method stub
return null;
}
}

View File

@ -1,21 +0,0 @@
package it.cavallium.warppi.gui.graphicengine.impl.framebuffer;
import java.io.IOException;
import it.cavallium.warppi.device.display.DisplayOutputDevice;
import it.cavallium.warppi.gui.graphicengine.impl.common.PngSkin;
public class FBSkin extends PngSkin {
public FBSkin(final String file) throws IOException {
super(file);
}
@Override
public void use(final DisplayOutputDevice d) {
@SuppressWarnings("unused")
final FBEngine dfb = (FBEngine) d;
// TODO: implement
}
}

View File

@ -20,7 +20,6 @@ import it.cavallium.warppi.device.input.KeyboardInputDevice;
import it.cavallium.warppi.device.input.PIHardwareTouchDevice; import it.cavallium.warppi.device.input.PIHardwareTouchDevice;
import it.cavallium.warppi.device.input.TouchInputDevice; import it.cavallium.warppi.device.input.TouchInputDevice;
import it.cavallium.warppi.gui.graphicengine.GraphicEngine; import it.cavallium.warppi.gui.graphicengine.GraphicEngine;
import it.cavallium.warppi.gui.graphicengine.impl.framebuffer.FBEngine;
import it.cavallium.warppi.gui.graphicengine.impl.jogl.JOGLDisplayOutputDevice; import it.cavallium.warppi.gui.graphicengine.impl.jogl.JOGLDisplayOutputDevice;
import it.cavallium.warppi.gui.graphicengine.impl.jogl.JOGLEngine; import it.cavallium.warppi.gui.graphicengine.impl.jogl.JOGLEngine;
import it.cavallium.warppi.util.Error; import it.cavallium.warppi.util.Error;
@ -29,7 +28,7 @@ public class HardwarePlatform implements Platform {
private final HardwareConsoleUtils cu; private final HardwareConsoleUtils cu;
private final HardwareGpio gi; private final HardwareGpio gi;
private final HardwareStorageUtils su; private final HardwarePlatformStorage su;
private final ImageUtils pu; private final ImageUtils pu;
private final String on; private final String on;
private final Map<String, GraphicEngine> el; private final Map<String, GraphicEngine> el;
@ -44,12 +43,11 @@ public class HardwarePlatform implements Platform {
public HardwarePlatform() { public HardwarePlatform() {
cu = new HardwareConsoleUtils(); cu = new HardwareConsoleUtils();
gi = new HardwareGpio(); gi = new HardwareGpio();
su = new HardwareStorageUtils(); su = new HardwarePlatformStorage();
pu = new HardwareImageUtils(); pu = new HardwareImageUtils();
on = System.getProperty("os.name").toLowerCase(); on = System.getProperty("os.name").toLowerCase();
el = new HashMap<>(); el = new HashMap<>();
el.put("GPU engine", new JOGLEngine()); el.put("GPU engine", new JOGLEngine(480, 320));
el.put("framebuffer engine", new FBEngine());
settings = new HardwareSettings(); settings = new HardwareSettings();
} }
@ -64,7 +62,7 @@ public class HardwarePlatform implements Platform {
} }
@Override @Override
public StorageUtils getStorageUtils() { public PlatformStorage getPlatformStorage() {
return su; return su;
} }
@ -151,10 +149,10 @@ public class HardwarePlatform implements Platform {
@Override @Override
public List<String> getRuleFilePaths() throws IOException { public List<String> getRuleFilePaths() throws IOException {
final File dslRulesPath = getStorageUtils().get("rules/"); final File dslRulesPath = getPlatformStorage().get("rules/");
List<String> paths = new ArrayList<>(); List<String> paths = new ArrayList<>();
if (dslRulesPath.exists()) { if (dslRulesPath.exists()) {
for (final File file : getStorageUtils().walk(dslRulesPath)) { for (final File file : getPlatformStorage().walk(dslRulesPath)) {
final String path = file.toString(); final String path = file.toString();
if (path.endsWith(".rules")) { if (path.endsWith(".rules")) {
paths.add(path); paths.add(path);
@ -218,6 +216,11 @@ public class HardwarePlatform implements Platform {
return backlightOutputDevice; return backlightOutputDevice;
} }
@Override
public DeviceStateDevice getDeviceStateDevice() {
return null;
}
@Override @Override
public void setArguments(StartupArguments args) { public void setArguments(StartupArguments args) {
this.args = args; this.args = args;

View File

@ -26,10 +26,10 @@ import java.util.stream.Stream;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import it.cavallium.warppi.Platform.StorageUtils; import it.cavallium.warppi.Platform.PlatformStorage;
import it.cavallium.warppi.util.ClassUtils; import it.cavallium.warppi.util.ClassUtils;
public class HardwareStorageUtils implements StorageUtils { public class HardwarePlatformStorage implements PlatformStorage {
@Override @Override
public boolean exists(final File f) { public boolean exists(final File f) {
return f.exists(); return f.exists();
@ -188,11 +188,11 @@ public class HardwareStorageUtils implements StorageUtils {
int i = 0; int i = 0;
for (final int opt : options) { for (final int opt : options) {
switch (opt) { switch (opt) {
case StorageUtils.OpenOptionCreate: { case PlatformStorage.OpenOptionCreate: {
noptions[i] = StandardOpenOption.CREATE; noptions[i] = StandardOpenOption.CREATE;
break; break;
} }
case StorageUtils.OpenOptionWrite: { case PlatformStorage.OpenOptionWrite: {
noptions[i] = StandardOpenOption.WRITE; noptions[i] = StandardOpenOption.WRITE;
break; break;
} }
@ -213,7 +213,7 @@ public class HardwareStorageUtils implements StorageUtils {
} }
@Override @Override
public String getBasePath() { public File getRootPath() {
return ""; return new File("");
} }
} }

View File

@ -1 +0,0 @@
/buffermanager.c

View File

@ -1,17 +0,0 @@
cmake_minimum_required(VERSION 2.8)
project(picalculatornative)
SET(COMPILE_DEFINITIONS -Werror)
find_package(JNI REQUIRED)
include_directories(${JNI_INCLUDE_DIRS})
include_directories(/opt/vc/include)
include_directories(/opt/vc/include/interface/vcos/pthreads)
include_directories(/opt/vc/include/interface/vmcs_host)
include_directories(/opt/vc/include/interface/vmcs_host/linux)
link_directories(/opt/vc/lib)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES TestJNI.cpp)
add_library(picalculatornative SHARED ${SOURCE_FILES})

View File

@ -1,75 +0,0 @@
#include <jni.h>
#include <stdio.h>
#include <stdio.h>
#include <syslog.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "TestJNI.h"
int fbfd = -1;
char *fbp = nullptr;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
JNIEXPORT void JNICALL Java_org_warp_picalculator_TestJNI_disposeDisplayBuffer(JNIEnv *env, jobject thisObj)
{
if (fbp != nullptr) {
munmap(fbp, finfo.smem_len);
fbp = nullptr;
}
if (fbfd != -1) {
close(fbfd);
fbfd = -1;
}
return;
}
JNIEXPORT jobject JNICALL Java_org_warp_picalculator_TestJNI_getDisplayBuffer(JNIEnv *env, jobject thisObj)
{
syslog(LOG_INFO, "[JNI NATIVE] INIT");
fbfd = open("/dev/fb1", O_RDWR);
if (fbfd == -1) {
syslog(LOG_ERR, "Unable to open secondary display");
return NULL;
}
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {
syslog(LOG_ERR, "Unable to get secondary display information");
return NULL;
}
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
syslog(LOG_ERR, "Unable to get secondary display information");
return NULL;
}
syslog(LOG_INFO, "Second display is %d x %d %dbps\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
fbp = (char*) mmap(0, finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
if (fbp <= 0) {
syslog(LOG_ERR, "Unable to create mamory mapping");
close(fbfd);
return NULL;
}
char* class_name = "org/warp/picalculator/MmapByteBuffer";
jclass clz = env->FindClass(class_name);
if (clz == NULL) {
printf("Error, could not find class '%s'\n", class_name);
return NULL;
}
char* signature = "(IIILjava/nio/ByteBuffer;)V";
jmethodID constructor = env->GetMethodID( clz, "<init>", signature);
if (constructor == NULL) {
printf("Error, could not find constructor %s %s\n", class_name, signature);
return NULL;
}
syslog(LOG_INFO, "[JNI NATIVE] DONE");
return env->NewObject(clz, constructor, fbfd, fbp, finfo.smem_len,
env->NewDirectByteBuffer(fbp, finfo.smem_len));
}

View File

@ -1,29 +0,0 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_warp_picalculator_TestJNI */
#ifndef _Included_org_warp_picalculator_TestJNI
#define _Included_org_warp_picalculator_TestJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_warp_picalculator_TestJNI
* Method: getDisplayBuffer
* Signature: ()Lorg/warp/picalculator/MmapByteBuffer;
*/
JNIEXPORT jobject JNICALL Java_org_warp_picalculator_TestJNI_getDisplayBuffer
(JNIEnv *, jobject);
/*
* Class: org_warp_picalculator_TestJNI
* Method: disposeDisplayBuffer
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_warp_picalculator_TestJNI_disposeDisplayBuffer
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif

Binary file not shown.

View File

@ -1,32 +0,0 @@
# Define a variable for classpath
CLASS_PATH = ../../../target/classes
PATH1A = it/cavallium/warppi
PATH1B = it.cavallium.warppi
# Define a virtual path for .class in the bin directory
vpath %.class $(CLASS_PATH)/$(PATH1A)
all : picalculatornative.so
# $@ matches the target, $< matches the first dependancy
picalculatornative.so : TestJNI.o
gcc -m64 -mtune=generic -Wl,--add-stdcall-alias -shared -o ../resources/$@ $<
# $@ matches the target, $< matches the first dependancy
picalculatornative.dll : windows_TestJNI.o
x86_64-w64-mingw32-gcc.exe -m64 -mtune=generic -Wl,--add-stdcall-alias -shared -o ../resources/$@ $<
# $@ matches the target, $< matches the first dependancy
windows_TestJNI.o : TestJNI.c TestJNI.h
x86_64-w64-mingw32-gcc.exe -m64 -mtune=generic -I"G:\Program Files\Java\jdk1.8.0_144\include" -I"G:\Program Files\Java\jdk1.8.0_144\include\win32" -c $< -o $@
# $@ matches the target, $< matches the first dependancy
TestJNI.o : TestJNI.c TestJNI.h
gcc -m64 -mtune=generic -I"G:\Program Files\Java\jdk1.8.0_144\include" -I"G:\Program Files\Java\jdk1.8.0_144\include\win32" -c $< -o $@
# $* matches the target filename without the extension
TestJNI.h : TestJNI.class
javah -o "$*.h" -classpath "$(CLASS_PATH)" $(PATH1B).$*
clean :
rm TestJNI.h TestJNI.o ../resources/picalculatornative.dll

View File

@ -91,10 +91,10 @@
<configuration> <configuration>
<mainClass>it.cavallium.warppi.teavm.TeaVMBoot</mainClass> <mainClass>it.cavallium.warppi.teavm.TeaVMBoot</mainClass>
<debugInformationGenerated>false</debugInformationGenerated> <debugInformationGenerated>false</debugInformationGenerated>
<sourceMapsGenerated>true</sourceMapsGenerated> <sourceMapsGenerated>false</sourceMapsGenerated>
<sourceFilesCopied>true</sourceFilesCopied> <sourceFilesCopied>false</sourceFilesCopied>
<optimizationLevel>SIMPLE</optimizationLevel> <optimizationLevel>SIMPLE</optimizationLevel>
<minifying>true</minifying> <minifying>false</minifying>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>

View File

@ -1,17 +1,21 @@
package it.cavallium.warppi.gui.graphicengine.html; package it.cavallium.warppi.gui.graphicengine.html;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.net.URL;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.lang3.ArrayUtils; import it.cavallium.warppi.teavm.TeaVMStorageUtils;
import org.teavm.jso.JSBody;
import org.teavm.jso.JSFunctor;
import org.teavm.jso.JSObject;
import org.teavm.jso.browser.Window; import org.teavm.jso.browser.Window;
import org.teavm.jso.canvas.CanvasImageSource;
import org.teavm.jso.dom.events.Event; import org.teavm.jso.dom.events.Event;
import org.teavm.jso.dom.html.HTMLDocument; import org.teavm.jso.dom.html.HTMLDocument;
import org.teavm.jso.dom.html.HTMLImageElement; import org.teavm.jso.dom.html.HTMLImageElement;
import it.cavallium.warppi.WarpPI; import it.cavallium.warppi.WarpPI;
import it.cavallium.warppi.Platform.Semaphore;
import it.cavallium.warppi.device.display.DisplayOutputDevice; import it.cavallium.warppi.device.display.DisplayOutputDevice;
import it.cavallium.warppi.gui.graphicengine.Skin; import it.cavallium.warppi.gui.graphicengine.Skin;
@ -22,8 +26,7 @@ public class HtmlSkin implements Skin {
private int[] skinSize; private int[] skinSize;
private boolean initd; private boolean initd;
private CanvasImageSource imgEl;
private HTMLImageElement imgEl;
public HtmlSkin(final String file) throws IOException { public HtmlSkin(final String file) throws IOException {
load(file); load(file);
@ -38,25 +41,35 @@ public class HtmlSkin implements Skin {
@Override @Override
public void load(String file) throws IOException { public void load(String file) throws IOException {
url = WarpPI.getPlatform().getStorageUtils().getBasePath() + (!file.startsWith("/") ? "/" : "") + file; File path = new File(WarpPI.getPlatform().getPlatformStorage().getRootPath(), file);
this.url = TeaVMStorageUtils.getUrl(path).toString();
} }
@Override @Override
public void initialize(final DisplayOutputDevice d) { public void initialize(final DisplayOutputDevice d) {
final HTMLDocument doc = Window.current().getDocument(); final HTMLDocument doc = Window.current().getDocument();
AtomicBoolean done = new AtomicBoolean(false); AtomicBoolean done = new AtomicBoolean(false);
imgEl = doc.createElement("img").cast();
imgEl.addEventListener("load", (Event e) -> { loadImage(url, (width, height, imageSource) -> {
skinSize = new int[] {width, height};
this.imgEl = imageSource;
done.set(true); done.set(true);
}); });
imgEl.setSrc(url);
while (!done.get()) { while (!done.get()) {
try {Thread.sleep(15);} catch (Exception e) {} try {Thread.sleep(15);} catch (Exception e) {}
} }
skinSize = new int[] { imgEl.getNaturalWidth(), imgEl.getNaturalHeight() };
initd = true; initd = true;
} }
@JSBody(params = { "url", "loadHandler" }, script = "var image = new Image(); image.onload = function(evt) { loadHandler(image.naturalWidth, image.naturalHeight, image);}; image.src = url;")
public static native void loadImage(String url, LoadHandler loadHandler);
@JSFunctor
public interface LoadHandler extends JSObject {
void onLoad(int width, int height, CanvasImageSource imageSource);
}
@Override @Override
public boolean isInitialized() { public boolean isInitialized() {
return initd; return initd;
@ -76,7 +89,7 @@ public class HtmlSkin implements Skin {
return url; return url;
} }
public final HTMLImageElement getImgElement() { public final CanvasImageSource getImgElement() {
return imgEl; return imgEl;
} }
} }

View File

@ -4,9 +4,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
import it.cavallium.warppi.boot.StartupArguments; import it.cavallium.warppi.boot.StartupArguments;
@ -24,7 +22,6 @@ import org.teavm.jso.dom.html.HTMLDocument;
import it.cavallium.warppi.Platform; import it.cavallium.warppi.Platform;
import it.cavallium.warppi.device.display.DisplayOutputDevice; import it.cavallium.warppi.device.display.DisplayOutputDevice;
import it.cavallium.warppi.gui.graphicengine.GraphicEngine;
import it.cavallium.warppi.gui.graphicengine.html.HtmlEngine; import it.cavallium.warppi.gui.graphicengine.html.HtmlEngine;
import it.cavallium.warppi.util.Error; import it.cavallium.warppi.util.Error;
@ -32,7 +29,7 @@ public class TeaVMPlatform implements Platform {
private final TeaVMConsoleUtils cu; private final TeaVMConsoleUtils cu;
private final TeaVMGpio gi; private final TeaVMGpio gi;
private final TeaVMStorageUtils su; private final TeaVMPlatformStorage su;
private final String on; private final String on;
private final TeaVMImageUtils pu; private final TeaVMImageUtils pu;
private final TeaVMSettings settings; private final TeaVMSettings settings;
@ -46,7 +43,7 @@ public class TeaVMPlatform implements Platform {
public TeaVMPlatform() { public TeaVMPlatform() {
cu = new TeaVMConsoleUtils(); cu = new TeaVMConsoleUtils();
gi = new TeaVMGpio(); gi = new TeaVMGpio();
su = new TeaVMStorageUtils(); su = new TeaVMPlatformStorage();
pu = new TeaVMImageUtils(); pu = new TeaVMImageUtils();
on = "JavaScript"; on = "JavaScript";
settings = new TeaVMSettings(); settings = new TeaVMSettings();
@ -63,7 +60,7 @@ public class TeaVMPlatform implements Platform {
} }
@Override @Override
public StorageUtils getStorageUtils() { public PlatformStorage getPlatformStorage() {
return su; return su;
} }
@ -157,8 +154,8 @@ public class TeaVMPlatform implements Platform {
*/ */
@Override @Override
public List<String> getRuleFilePaths() throws IOException { public List<String> getRuleFilePaths() throws IOException {
try (final InputStream listStream = getStorageUtils().getResourceStream("/rules.list")) { try (final InputStream listStream = getPlatformStorage().getResourceStream("/rules.list")) {
return getStorageUtils().readAllLines(listStream); return getPlatformStorage().readAllLines(listStream);
} }
} }

View File

@ -0,0 +1,223 @@
package it.cavallium.warppi.teavm;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.teavm.jso.browser.Window;
import it.cavallium.warppi.Platform.PlatformStorage;
public class TeaVMPlatformStorage implements PlatformStorage {
@Override
public boolean exists(final File f) {
return f.exists();
}
@Override
public File get(final String path) {
return new File(path);
}
private static String join(final String[] list, final String conjunction) {
final StringBuilder sb = new StringBuilder();
boolean first = true;
for (final String item : list) {
if (first)
first = false;
else
sb.append(conjunction);
sb.append(item);
}
return sb.toString();
}
@Override
public File get(final String... path) {
return new File(TeaVMPlatformStorage.join(path, File.separator));
}
private static Map<String, File> resourcesCache = new HashMap<>();
@Override
public File getResource(final String path) throws IOException, URISyntaxException {
try {
File targetFile;
if (TeaVMPlatformStorage.resourcesCache.containsKey(path))
if ((targetFile = TeaVMPlatformStorage.resourcesCache.get(path)).exists())
return targetFile;
else
TeaVMPlatformStorage.resourcesCache.remove(path);
final URL res = TeaVMStorageUtils.getUrl(new File(getRootPath(), path));
final InputStream initialStream = res.openStream();
final byte[] buffer = new byte[initialStream.available()];
initialStream.read(buffer);
targetFile = File.createTempFile("res", ".bin");
targetFile.createNewFile();
final FileOutputStream outStream = new FileOutputStream(targetFile);
outStream.write(buffer);
outStream.close();
TeaVMPlatformStorage.resourcesCache.put(path, targetFile);
return targetFile;
} catch (final java.lang.IllegalArgumentException e) {
throw e;
}
}
@Override
public InputStream getResourceStream(final String path) throws IOException {
try {
File targetFile;
if (TeaVMPlatformStorage.resourcesCache.containsKey(path))
if ((targetFile = TeaVMPlatformStorage.resourcesCache.get(path)).exists())
return new FileInputStream(targetFile);
else
TeaVMPlatformStorage.resourcesCache.remove(path);
final URL res = TeaVMStorageUtils.getUrl(new File(getRootPath(), path));
final InputStream initialStream = res.openStream();
final byte[] buffer = new byte[initialStream.available()];
initialStream.read(buffer);
targetFile = File.createTempFile("res", ".bin");
targetFile.createNewFile();
final FileOutputStream outStream = new FileOutputStream(targetFile);
outStream.write(buffer);
outStream.close();
TeaVMPlatformStorage.resourcesCache.put(path, targetFile);
return new FileInputStream(targetFile);
} catch (final java.lang.IllegalArgumentException e) {
throw e;
}
}
@Override
public boolean doesResourceExist(final String path) throws IOException {
try {
File targetFile;
if (TeaVMPlatformStorage.resourcesCache.containsKey(path))
if ((targetFile = TeaVMPlatformStorage.resourcesCache.get(path)).exists())
return true;
else
TeaVMPlatformStorage.resourcesCache.remove(path);
return true;
} catch (final java.lang.IllegalArgumentException e) {
throw e;
}
}
@Override
public List<String> readAllLines(final File file) throws IOException {
final Reader reader_ = new InputStreamReader(new FileInputStream(file), Charset.defaultCharset());
final BufferedReader reader = reader_ instanceof BufferedReader ? (BufferedReader) reader_ : new BufferedReader(reader_);
final List<String> list = new ArrayList<>();
String line = reader.readLine();
while (line != null) {
list.add(line);
line = reader.readLine();
}
reader.close();
return list;
}
// Reading an InputStream as a String is implemented this way
// because, on TeaVM, more convenient methods (such as IOUtils.toString) hang.
@Override
public String read(final InputStream input) throws IOException {
final int BUFFER_SIZE = 1024;
final StringBuilder builder = new StringBuilder();
try (final Reader reader = new InputStreamReader(input, StandardCharsets.UTF_8)) {
final char[] buffer = new char[BUFFER_SIZE];
int readCount;
while ((readCount = reader.read(buffer)) != -1) {
builder.append(buffer, 0, readCount);
}
}
return builder.toString();
}
@Override
public List<File> walk(final File dir) throws IOException {
final List<File> out = new ArrayList<>();
final File[] filesList = dir.listFiles();
if (filesList == null)
out.add(dir);
else
for (final File f : filesList)
if (f.isDirectory()) {
if (f.canRead())
out.addAll(walk(dir));
} else if (f.isFile())
if (f.canRead())
out.add(f);
return out;
}
@Override
public File relativize(final File rulesPath, final File f) {
return f;
}
@Override
public File resolve(final File file, final String string) {
return new File(file.getAbsolutePath() + File.separatorChar + string);
}
@Override
public File getParent(final File f) {
return f.getParentFile();
}
@Override
public void createDirectories(final File dir) throws IOException {
dir.mkdirs();
}
@Override
public void write(final File f, final byte[] bytes, final int... options) throws IOException {
boolean create = false;
for (final int opt : options)
if (opt == PlatformStorage.OpenOptionCreate)
create = true;
if (f.exists() == false)
if (create) {
if (!f.createNewFile())
throw new IOException("File doesn't exist, can't create it!");
} else
throw new IOException("File doesn't exist.");
final FileOutputStream stream = new FileOutputStream(f);
stream.write(bytes);
stream.close();
}
@Override
public List<String> readAllLines(final InputStream input) throws IOException {
try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) {
String thisLine = null;
final ArrayList<String> output = new ArrayList<>();
while ((thisLine = buffer.readLine()) != null)
output.add(thisLine);
return output;
}
}
@Override
public File getRootPath() {
return new File("resources");
}
}

View File

@ -1,226 +1,46 @@
package it.cavallium.warppi.teavm; package it.cavallium.warppi.teavm;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.teavm.jso.browser.Window; import org.teavm.jso.browser.Window;
import it.cavallium.warppi.Platform.StorageUtils; import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
public class TeaVMStorageUtils implements StorageUtils { public class TeaVMStorageUtils {
@Override public static URL getUrl(File file) throws MalformedURLException {
public boolean exists(final File f) { String path = file.toString();
return f.exists(); if (path.startsWith("/")) {
} path = path.substring(1);
@Override
public File get(final String path) {
return new File(path);
}
private static String join(final String[] list, final String conjunction) {
final StringBuilder sb = new StringBuilder();
boolean first = true;
for (final String item : list) {
if (first)
first = false;
else
sb.append(conjunction);
sb.append(item);
} }
return sb.toString();
}
@Override String protocol = Window.current().getLocation().getProtocol();
public File get(final String... path) { String host = Window.current().getLocation().getHost();
return new File(TeaVMStorageUtils.join(path, File.separator)); String indexPath = Window.current().getLocation().getPathName();
} String websiteDir;
if (indexPath.endsWith("/")) {
private static Map<String, File> resourcesCache = new HashMap<>(); websiteDir = indexPath;
} else {
@Override String[] parts = indexPath.split("/");
public File getResource(final String path) throws IOException, URISyntaxException { String[] dirParts = Arrays.copyOf(parts, parts.length - 1);
try { StringBuilder dirBuilder = new StringBuilder("/");
File targetFile; for (String dirPart : dirParts) {
if (TeaVMStorageUtils.resourcesCache.containsKey(path)) dirBuilder.append(dirPart);
if ((targetFile = TeaVMStorageUtils.resourcesCache.get(path)).exists()) dirBuilder.append('/');
return targetFile;
else
TeaVMStorageUtils.resourcesCache.remove(path);
final URL res = new URL(getBasePath() + path);
final InputStream initialStream = res.openStream();
final byte[] buffer = new byte[initialStream.available()];
initialStream.read(buffer);
targetFile = File.createTempFile("res", ".bin");
targetFile.createNewFile();
final FileOutputStream outStream = new FileOutputStream(targetFile);
outStream.write(buffer);
outStream.close();
TeaVMStorageUtils.resourcesCache.put(path, targetFile);
return targetFile;
} catch (final java.lang.IllegalArgumentException e) {
throw e;
}
}
@Override
public InputStream getResourceStream(final String path) throws IOException {
try {
File targetFile;
if (TeaVMStorageUtils.resourcesCache.containsKey(path))
if ((targetFile = TeaVMStorageUtils.resourcesCache.get(path)).exists())
return new FileInputStream(targetFile);
else
TeaVMStorageUtils.resourcesCache.remove(path);
final URL res = new URL(getBasePath() + (path.startsWith("/") ? path : "/" + path));
final InputStream initialStream = res.openStream();
final byte[] buffer = new byte[initialStream.available()];
initialStream.read(buffer);
targetFile = File.createTempFile("res", ".bin");
targetFile.createNewFile();
final FileOutputStream outStream = new FileOutputStream(targetFile);
outStream.write(buffer);
outStream.close();
TeaVMStorageUtils.resourcesCache.put(path, targetFile);
return new FileInputStream(targetFile);
} catch (final java.lang.IllegalArgumentException e) {
throw e;
}
}
@Override
public boolean doesResourceExist(final String path) throws IOException {
try {
File targetFile;
if (TeaVMStorageUtils.resourcesCache.containsKey(path))
if ((targetFile = TeaVMStorageUtils.resourcesCache.get(path)).exists())
return true;
else
TeaVMStorageUtils.resourcesCache.remove(path);
return true;
} catch (final java.lang.IllegalArgumentException e) {
throw e;
}
}
@Override
public List<String> readAllLines(final File file) throws IOException {
final Reader reader_ = new InputStreamReader(new FileInputStream(file), Charset.defaultCharset());
final BufferedReader reader = reader_ instanceof BufferedReader ? (BufferedReader) reader_ : new BufferedReader(reader_);
final List<String> list = new ArrayList<>();
String line = reader.readLine();
while (line != null) {
list.add(line);
line = reader.readLine();
}
reader.close();
return list;
}
// Reading an InputStream as a String is implemented this way
// because, on TeaVM, more convenient methods (such as IOUtils.toString) hang.
@Override
public String read(final InputStream input) throws IOException {
final int BUFFER_SIZE = 1024;
final StringBuilder builder = new StringBuilder();
try (final Reader reader = new InputStreamReader(input, StandardCharsets.UTF_8)) {
final char[] buffer = new char[BUFFER_SIZE];
int readCount;
while ((readCount = reader.read(buffer)) != -1) {
builder.append(buffer, 0, readCount);
} }
websiteDir = dirBuilder.toString();
} }
return builder.toString(); String fullUrl = protocol + "//" + host + websiteDir;
} if (fullUrl.endsWith("/")) {
fullUrl = fullUrl.substring(0, fullUrl.length() - 1);
@Override
public List<File> walk(final File dir) throws IOException {
final List<File> out = new ArrayList<>();
final File[] filesList = dir.listFiles();
if (filesList == null)
out.add(dir);
else
for (final File f : filesList)
if (f.isDirectory()) {
if (f.canRead())
out.addAll(walk(dir));
} else if (f.isFile())
if (f.canRead())
out.add(f);
return out;
}
@Override
public File relativize(final File rulesPath, final File f) {
return f;
}
@Override
public File resolve(final File file, final String string) {
return new File(file.getAbsolutePath() + File.separatorChar + string);
}
@Override
public File getParent(final File f) {
return f.getParentFile();
}
@Override
public void createDirectories(final File dir) throws IOException {
dir.mkdirs();
}
@Override
public void write(final File f, final byte[] bytes, final int... options) throws IOException {
boolean create = false;
for (final int opt : options)
if (opt == StorageUtils.OpenOptionCreate)
create = true;
if (f.exists() == false)
if (create) {
if (!f.createNewFile())
throw new IOException("File doesn't exist, can't create it!");
} else
throw new IOException("File doesn't exist.");
final FileOutputStream stream = new FileOutputStream(f);
stream.write(bytes);
stream.close();
}
@Override
public List<String> readAllLines(final InputStream input) throws IOException {
try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) {
String thisLine = null;
final ArrayList<String> output = new ArrayList<>();
while ((thisLine = buffer.readLine()) != null)
output.add(thisLine);
return output;
} }
}
@Override String urlString = fullUrl + "/" + path;
public String getBasePath() { try {
final String fullurl = Window.current().getLocation().getFullURL(); return new URL(urlString);
if (fullurl.charAt(fullurl.length() - 1) == '/') } catch (MalformedURLException e) {
return fullurl + "resources"; System.out.println("Errored URL: " + fullUrl + "/" + path);
else throw e;
return fullurl + "/resources"; }
} }
} }