diff --git a/.gitignore b/.gitignore index de13b3b0..3ea645b5 100644 --- a/.gitignore +++ b/.gitignore @@ -150,4 +150,5 @@ /lib.darcula/build/ /lib.nanohttpd/build/ /praxis.data/build/ -/praxis.data/nbproject/private/ \ No newline at end of file +/praxis.data/nbproject/private/ +/lib.jna.platform/build/ \ No newline at end of file diff --git a/lib.jna.platform/build.xml b/lib.jna.platform/build.xml new file mode 100644 index 00000000..aa5f4e7b --- /dev/null +++ b/lib.jna.platform/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.sun.jna.platform. + + diff --git a/lib.jna.platform/manifest.mf b/lib.jna.platform/manifest.mf new file mode 100644 index 00000000..267714f9 --- /dev/null +++ b/lib.jna.platform/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +AutoUpdate-Show-In-Client: true +OpenIDE-Module: com.sun.jna.platform +OpenIDE-Module-Localizing-Bundle: com/sun/jna/platform/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 + diff --git a/lib.jna.platform/nbproject/build-impl.xml b/lib.jna.platform/nbproject/build-impl.xml new file mode 100644 index 00000000..f7c2cb00 --- /dev/null +++ b/lib.jna.platform/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib.jna.platform/nbproject/genfiles.properties b/lib.jna.platform/nbproject/genfiles.properties new file mode 100644 index 00000000..ed01dd86 --- /dev/null +++ b/lib.jna.platform/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=5dd71efe +build.xml.script.CRC32=c08ae6e9 +build.xml.stylesheet.CRC32=a56c6a5b@2.71.1 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=5dd71efe +nbproject/build-impl.xml.script.CRC32=a5bb51d6 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.71.1 diff --git a/lib.jna.platform/nbproject/project.properties b/lib.jna.platform/nbproject/project.properties new file mode 100644 index 00000000..8644bf55 --- /dev/null +++ b/lib.jna.platform/nbproject/project.properties @@ -0,0 +1,3 @@ +is.autoload=true +javac.compilerargs=-Xlint -Xlint:-serial +javac.source=1.8 diff --git a/lib.jna.platform/nbproject/project.xml b/lib.jna.platform/nbproject/project.xml new file mode 100644 index 00000000..15102662 --- /dev/null +++ b/lib.jna.platform/nbproject/project.xml @@ -0,0 +1,37 @@ + + + org.netbeans.modules.apisupport.project + + + com.sun.jna.platform + + + + com.sun.jna + + + + 3.5.1 + + + + + com.sun.jna.platform + com.sun.jna.platform.dnd + com.sun.jna.platform.mac + com.sun.jna.platform.unix + com.sun.jna.platform.win32 + com.sun.jna.platform.win32.COM + com.sun.jna.platform.win32.COM.tlb + com.sun.jna.platform.win32.COM.tlb.imp + com.sun.jna.platform.win32.COM.util + com.sun.jna.platform.win32.COM.util.annotation + com.sun.jna.platform.wince + + + ext/jna-platform-4.2.2.jar + release/modules/ext/jna-platform-4.2.2.jar + + + + diff --git a/lib.jna.platform/nbproject/suite.properties b/lib.jna.platform/nbproject/suite.properties new file mode 100644 index 00000000..29d7cc9b --- /dev/null +++ b/lib.jna.platform/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/lib.jna.platform/release/modules/ext/jna-platform-4.2.2.jar b/lib.jna.platform/release/modules/ext/jna-platform-4.2.2.jar new file mode 100644 index 00000000..f3a9fd2b Binary files /dev/null and b/lib.jna.platform/release/modules/ext/jna-platform-4.2.2.jar differ diff --git a/lib.jna.platform/src/com/sun/jna/platform/Bundle.properties b/lib.jna.platform/src/com/sun/jna/platform/Bundle.properties new file mode 100644 index 00000000..ea0baa15 --- /dev/null +++ b/lib.jna.platform/src/com/sun/jna/platform/Bundle.properties @@ -0,0 +1 @@ +OpenIDE-Module-Name=lib.jna.platform diff --git a/nbproject/project.properties b/nbproject/project.properties index 164e7586..8a94ecd5 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -65,9 +65,11 @@ modules=\ ${project.net.neilcsmith.praxis.code.services}:\ ${project.com.bulenkov.darcula}:\ ${project.fi.iki.elonen}:\ - ${project.net.neilcsmith.praxis.data} + ${project.net.neilcsmith.praxis.data}:\ + ${project.com.sun.jna.platform} project.com.bulenkov.darcula=lib.darcula project.com.sun.jna=lib.jna +project.com.sun.jna.platform=lib.jna.platform project.com.tinkerforge=lib.tinkerforge project.de.sciss.net=lib.netutil project.fi.iki.elonen=lib.nanohttpd diff --git a/praxis.video.gst1/nbproject/genfiles.properties b/praxis.video.gst1/nbproject/genfiles.properties index 8c6a8d94..1fb18b3d 100644 --- a/praxis.video.gst1/nbproject/genfiles.properties +++ b/praxis.video.gst1/nbproject/genfiles.properties @@ -1,8 +1,8 @@ -build.xml.data.CRC32=0c087fce +build.xml.data.CRC32=5f78fa18 build.xml.script.CRC32=c35d8958 -build.xml.stylesheet.CRC32=a56c6a5b@2.67.1 +build.xml.stylesheet.CRC32=a56c6a5b@2.71.1 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=0c087fce +nbproject/build-impl.xml.data.CRC32=5f78fa18 nbproject/build-impl.xml.script.CRC32=fb5821b9 -nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.67.1 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.71.1 diff --git a/praxis.video.gst1/nbproject/project.xml b/praxis.video.gst1/nbproject/project.xml index 3fead839..560feffd 100644 --- a/praxis.video.gst1/nbproject/project.xml +++ b/praxis.video.gst1/nbproject/project.xml @@ -6,6 +6,22 @@ net.neilcsmith.praxis.video.gst1 + + com.sun.jna + + + + 3.5.1 + + + + com.sun.jna.platform + + + + 1.0 + + net.neilcsmith.praxis.core @@ -22,6 +38,14 @@ 1.0 + + net.neilcsmith.praxis.settings + + + + 1.0 + + net.neilcsmith.praxis.video @@ -55,7 +79,9 @@ - + + net.neilcsmith.praxis.video.gst1 + diff --git a/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/GStreamerSettings.java b/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/GStreamerSettings.java new file mode 100644 index 00000000..01374499 --- /dev/null +++ b/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/GStreamerSettings.java @@ -0,0 +1,97 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2016 Neil C Smith. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3 only, as + * published by the Free Software Foundation. + * + * This code 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 + * version 3 for more details. + * + * You should have received a copy of the GNU General Public License version 3 + * along with this work; if not, see http://www.gnu.org/licenses/ + * + * + * Please visit http://neilcsmith.net if you need additional information or + * have any questions. + */ +package net.neilcsmith.praxis.video.gst1; + +import com.sun.jna.Platform; +import net.neilcsmith.praxis.settings.Settings; + +/** + * + * @author Neil C Smith (http://neilcsmith.net) + */ +public class GStreamerSettings { + + private final static String KEY_CAPTURE_PREFIX = "video.gstreamer.capture"; + private final static String KEY_LIBRARY_PATH = "video.gstreamer.path"; + + private final static String DEFAULT_CAPTURE_PREFIX; + private final static String DEFAULT_LIBRARY_PATH; + + static { + if (Platform.isWindows()) { + DEFAULT_CAPTURE_PREFIX = "ksvideosrc device-index="; + if (Platform.is64Bit()) { + DEFAULT_LIBRARY_PATH = "C:\\gstreamer\\1.0\\x86_64\\bin\\"; + } else { + DEFAULT_LIBRARY_PATH = "C:\\gstreamer\\1.0\\x86\\bin\\"; + } + } else if (Platform.isMac()) { + DEFAULT_CAPTURE_PREFIX = "qtkitvideosrc device-index="; + DEFAULT_LIBRARY_PATH = "/Library/Frameworks/GStreamer.framework/Libraries/"; + } else { + DEFAULT_CAPTURE_PREFIX = "v4l2src device=/dev/video"; + DEFAULT_LIBRARY_PATH = ""; + } + } + + public static String getDefaultCaptureDevice(int idx) { + if (idx < 1) { + throw new IllegalArgumentException(); + } + return DEFAULT_CAPTURE_PREFIX + (idx - 1); + } + + public static void resetCaptureDevice(int idx) { + setCaptureDevice(idx, null); + } + + public static String getCaptureDevice(int idx) { + if (idx < 1) { + throw new IllegalArgumentException(); + } + return Settings.get(KEY_CAPTURE_PREFIX + idx, getDefaultCaptureDevice(idx)); + } + + public static void setCaptureDevice(int idx, String device) { + if (idx < 1) { + throw new IllegalArgumentException(); + } + Settings.put(KEY_CAPTURE_PREFIX + idx, device); + } + + public static String getDefaultLibraryPath() { + return DEFAULT_LIBRARY_PATH; + } + + public static void resetLibraryPath() { + setLibraryPath(null); + } + + public static String getLibraryPath() { + return Settings.get(KEY_LIBRARY_PATH, getDefaultLibraryPath()); + } + + public static void setLibraryPath(String libPath) { + Settings.put(KEY_LIBRARY_PATH, libPath); + } + +} diff --git a/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/AbstractGstDelegate.java b/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/AbstractGstDelegate.java index 0556dcad..9eaa0927 100644 --- a/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/AbstractGstDelegate.java +++ b/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/AbstractGstDelegate.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2015 Neil C Smith. + * Copyright 2016 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3 only, as @@ -74,7 +74,7 @@ public abstract class AbstractGstDelegate extends VideoDelegate { private volatile boolean looping; protected AbstractGstDelegate() { - Gst.init(); + GStreamerLibrary.getInstance().init(); state = new AtomicReference<>(State.New); surfaceLock = new ReentrantLock(); } diff --git a/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/BinDelegate.java b/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/BinDelegate.java index ff0ba58f..b4963870 100644 --- a/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/BinDelegate.java +++ b/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/BinDelegate.java @@ -52,7 +52,7 @@ public class BinDelegate extends AbstractGstDelegate { private int requestHeight; private int requestRate; - private BinDelegate(String binDescription) { + public BinDelegate(String binDescription) { this.binDescription = binDescription; } @@ -128,7 +128,7 @@ private String buildCapsString() { } - + @Deprecated public static BinDelegate create(String binDescription) { return new BinDelegate(binDescription); } diff --git a/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/GStreamerLibrary.java b/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/GStreamerLibrary.java new file mode 100644 index 00000000..71d2a4b4 --- /dev/null +++ b/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/GStreamerLibrary.java @@ -0,0 +1,85 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2016 Neil C Smith. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3 only, as + * published by the Free Software Foundation. + * + * This code 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 + * version 3 for more details. + * + * You should have received a copy of the GNU General Public License version 3 + * along with this work; if not, see http://www.gnu.org/licenses/ + * + * + * Please visit http://neilcsmith.net if you need additional information or + * have any questions. + * + */ +package net.neilcsmith.praxis.video.gst1.components; + +import com.sun.jna.Platform; +import com.sun.jna.platform.win32.Kernel32; +import java.io.File; +import java.util.logging.Level; +import java.util.logging.Logger; +import net.neilcsmith.praxis.video.gst1.GStreamerSettings; +import org.freedesktop.gstreamer.Gst; + +/** + * + * @author Neil C Smith + */ +class GStreamerLibrary { + + private static final GStreamerLibrary INSTANCE = new GStreamerLibrary(); + + private GStreamerLibrary() { + initLibraryPaths(); + } + + private void initLibraryPaths() { + String libPath = GStreamerSettings.getLibraryPath().trim(); + if (libPath.isEmpty()) { + return; + } + if (Platform.isWindows()) { + try { + Kernel32 k32 = Kernel32.INSTANCE; + String path = System.getenv("path"); + if (path == null || path.trim().isEmpty()) { + k32.SetEnvironmentVariable("path", libPath); + } else { + k32.SetEnvironmentVariable("path", libPath + File.pathSeparator + path); + } + return; + } catch (Throwable e) { + Logger.getLogger(GStreamerLibrary.class.getName()) + .log(Level.SEVERE, "Unable to set Windows library path", e); + // fall through + } + } + String jnaPath = System.getProperty("jna.library.path", "").trim(); + if (jnaPath.isEmpty()) { + System.setProperty("jna.library.path", libPath); + } else { + System.setProperty("jna.library.path", jnaPath + File.pathSeparator + libPath); + } + + } + + void init() { + Gst.init(); + } + + static GStreamerLibrary getInstance() { + return INSTANCE; + } + + + +} diff --git a/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/PlayBinDelegate.java b/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/PlayBinDelegate.java index 6a2410e6..f929aabf 100644 --- a/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/PlayBinDelegate.java +++ b/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/PlayBinDelegate.java @@ -46,7 +46,7 @@ public class PlayBinDelegate extends AbstractGstDelegate { private PlayBin pipe; private volatile double rate; - protected PlayBinDelegate(URI loc, String audioSink) { + public PlayBinDelegate(URI loc, String audioSink) { this.loc = loc; this.audioSink = audioSink.trim(); this.rate = 1; @@ -144,8 +144,4 @@ private void doSeek(boolean eos, long position) { pipe.getState(10, TimeUnit.MILLISECONDS); } - @Deprecated - public static PlayBinDelegate create(URI loc) { - return new PlayBinDelegate(loc, ""); - } } diff --git a/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/VideoCapture.java b/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/VideoCapture.java index a3fe6cce..e0c83de2 100644 --- a/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/VideoCapture.java +++ b/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/VideoCapture.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2015 Neil C Smith. + * Copyright 2016 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3 only, as @@ -38,7 +38,7 @@ import net.neilcsmith.praxis.impl.DefaultControlOutputPort; import net.neilcsmith.praxis.impl.TriggerControl; import net.neilcsmith.praxis.video.InvalidVideoResourceException; -import net.neilcsmith.praxis.video.VideoSettings; +import net.neilcsmith.praxis.video.gst1.GStreamerSettings; /** * @@ -158,7 +158,7 @@ public Argument execute() throws Exception { private String getDefaultDeviceDescription(String dev) { try { String dsc - = VideoSettings.getCaptureDevice(Integer.valueOf(dev)); + = GStreamerSettings.getCaptureDevice(Integer.valueOf(dev)); return dsc; } catch (Exception ex) { return null; @@ -167,7 +167,7 @@ private String getDefaultDeviceDescription(String dev) { } private VideoDelegate createDelegateFromDescription(String desc) { - return VideoDelegateFactory.getInstance().createCaptureDelegate(desc); + return new BinDelegate(desc); } } diff --git a/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/VideoDelegateFactory.java b/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/VideoDelegateFactory.java deleted file mode 100644 index 53ecf723..00000000 --- a/praxis.video.gst1/src/net/neilcsmith/praxis/video/gst1/components/VideoDelegateFactory.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2012 Neil C Smith. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3 only, as - * published by the Free Software Foundation. - * - * This code 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 - * version 3 for more details. - * - * You should have received a copy of the GNU General Public License version 3 - * along with this work; if not, see http://www.gnu.org/licenses/ - * - * - * Please visit http://neilcsmith.net if you need additional information or - * have any questions. - * - */ -package net.neilcsmith.praxis.video.gst1.components; - -import java.net.URI; -import java.util.logging.Logger; - -/** - * - * @author Neil C Smith - */ -class VideoDelegateFactory { - - private final static Logger LOG = Logger.getLogger(VideoDelegateFactory.class.getName()); - - private static VideoDelegateFactory instance = new VideoDelegateFactory(); - - private VideoDelegateFactory() { - preloadLibs(); - } - - private void preloadLibs() { -// try { -// for (GStreamerLibraryLoader loader : Lookup.getDefault().lookupAll(GStreamerLibraryLoader.class)) { -// -// try { -// loader.load(); -// } catch (Exception ex) { -// LOG.log(Level.WARNING, "Exception thrown while trying to load GStreamer libraries with loader " + loader, ex); -// } -// } -// } catch (Exception ex) { -// LOG.log(Level.WARNING, "Exception thrown while trying to load GStreamer library loaders", ex); -// } - } - - static VideoDelegateFactory getInstance() { - return instance; - } - - VideoDelegate createCaptureDelegate(String binDescription) { - return BinDelegate.create(binDescription); - } - - VideoDelegate createPlayBinDelegate(URI resource) { - return PlayBinDelegate.create(resource); - } - - -} diff --git a/praxis.video/src/net/neilcsmith/praxis/video/VideoSettings.java b/praxis.video/src/net/neilcsmith/praxis/video/VideoSettings.java index 0c02d93a..6f95bdd8 100644 --- a/praxis.video/src/net/neilcsmith/praxis/video/VideoSettings.java +++ b/praxis.video/src/net/neilcsmith/praxis/video/VideoSettings.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2015 Neil C Smith. + * Copyright 2016 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3 only, as @@ -35,34 +35,16 @@ public enum FullScreenMode { } private final static String KEY_FULLSCREENMODE = "video.fullscreenmode"; - private final static String KEY_CAPTURE_PREFIX = "video.capture"; - private final static String KEY_MEDIA_LIB = "video.medialib"; - - private final static String DEFAULT_MEDIA_LIB = "gstreamer-0.10"; + private final static boolean DEFAULT_FSEM; - private final static String DEFAULT_CAPTURE_PREFIX; - - @Deprecated - public final static String KEY_RENDERER = "video.renderer"; - - @Deprecated - private final static String DEFAULT_RENDERER = "Software"; - @Deprecated - private static final String DEFAULT_CAPTURE_SCHEME; static { String os = System.getProperty("os.name", ""); if (os.contains("Windows")) { - DEFAULT_CAPTURE_PREFIX = "ksvideosrc device-index="; - DEFAULT_CAPTURE_SCHEME = "ks"; DEFAULT_FSEM = false; } else if (os.contains("Mac") || os.contains("Darwin")) { - DEFAULT_CAPTURE_PREFIX = "qtkitvideosrc device-index="; - DEFAULT_CAPTURE_SCHEME = "qtkit"; DEFAULT_FSEM = true; } else { - DEFAULT_CAPTURE_PREFIX = "v4l2src device=/dev/video"; - DEFAULT_CAPTURE_SCHEME = "v4l2"; DEFAULT_FSEM = true; } @@ -102,51 +84,4 @@ public static boolean isFullScreenExclusive() { } } - public static String getDefaultCaptureDevice(int idx) { - if (idx < 1) { - throw new IllegalArgumentException(); - } - return DEFAULT_CAPTURE_PREFIX + (idx - 1); - } - - public static void resetCaptureDevice(int idx) { - setCaptureDevice(idx, null); - } - - public static String getCaptureDevice(int idx) { - if (idx < 1) { - throw new IllegalArgumentException(); - } - return Settings.get(KEY_CAPTURE_PREFIX + idx, getDefaultCaptureDevice(idx)); - } - - public static void setCaptureDevice(int idx, String device) { - if (idx < 1) { - throw new IllegalArgumentException(); - } - Settings.put(KEY_CAPTURE_PREFIX + idx, device); - } - - public static String getMediaLib() { - return Settings.get(KEY_MEDIA_LIB, DEFAULT_MEDIA_LIB); - } - - public static void setMediaLib(String lib) { - Settings.put(KEY_MEDIA_LIB, lib); - } - - public static void resetMediaLib() { - setMediaLib(null); - } - - @Deprecated - public static String getRenderer() { - return Settings.get(KEY_RENDERER, DEFAULT_RENDERER); - } - - @Deprecated - public static void setRenderer(String renderer) { - Settings.put(KEY_RENDERER, renderer); - } - }