@@ -14,7 +14,7 @@ ifeq ($(ARCH), lin) | |||||
LDFLAGS += -rdynamic \ | LDFLAGS += -rdynamic \ | ||||
-lpthread -lGL -ldl \ | -lpthread -lGL -ldl \ | ||||
$(shell pkg-config --libs gtk+-2.0) \ | $(shell pkg-config --libs gtk+-2.0) \ | ||||
-Ldep/lib -lGLEW -lglfw -ljansson -lspeexdsp -lcurl -lzip -lrtaudio -lrtmidi | |||||
-Ldep/lib -lGLEW -lglfw -ljansson -lspeexdsp -lcurl -lzip -lrtaudio -lrtmidi -lcrypto -lssl | |||||
TARGET = Rack | TARGET = Rack | ||||
endif | endif | ||||
@@ -23,7 +23,7 @@ ifeq ($(ARCH), mac) | |||||
CXXFLAGS += -DAPPLE -stdlib=libc++ | CXXFLAGS += -DAPPLE -stdlib=libc++ | ||||
LDFLAGS += -stdlib=libc++ -lpthread -ldl \ | LDFLAGS += -stdlib=libc++ -lpthread -ldl \ | ||||
-framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo \ | -framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo \ | ||||
-Ldep/lib -lGLEW -lglfw -ljansson -lspeexdsp -lcurl -lzip -lrtaudio -lrtmidi | |||||
-Ldep/lib -lGLEW -lglfw -ljansson -lspeexdsp -lcurl -lzip -lrtaudio -lrtmidi -lcrypto -lssl | |||||
TARGET = Rack | TARGET = Rack | ||||
BUNDLE = dist/$(TARGET).app | BUNDLE = dist/$(TARGET).app | ||||
endif | endif | ||||
@@ -33,7 +33,7 @@ ifeq ($(ARCH), win) | |||||
LDFLAGS += -static-libgcc -static-libstdc++ -lpthread \ | LDFLAGS += -static-libgcc -static-libstdc++ -lpthread \ | ||||
-Wl,--export-all-symbols,--out-implib,libRack.a -mwindows \ | -Wl,--export-all-symbols,--out-implib,libRack.a -mwindows \ | ||||
-lgdi32 -lopengl32 -lcomdlg32 -lole32 \ | -lgdi32 -lopengl32 -lcomdlg32 -lole32 \ | ||||
-Ldep/lib -lglew32 -lglfw3dll -lcurl -lzip -lrtaudio -lrtmidi \ | |||||
-Ldep/lib -lglew32 -lglfw3dll -lcurl -lzip -lrtaudio -lrtmidi -lcrypto -lssl \ | |||||
-Wl,-Bstatic -ljansson -lspeexdsp | -Wl,-Bstatic -ljansson -lspeexdsp | ||||
TARGET = Rack.exe | TARGET = Rack.exe | ||||
OBJECTS = Rack.res | OBJECTS = Rack.res | ||||
@@ -112,8 +112,14 @@ ifeq ($(ARCH), mac) | |||||
cp dep/lib/libspeexdsp.1.dylib $(BUNDLE)/Contents/MacOS/ | cp dep/lib/libspeexdsp.1.dylib $(BUNDLE)/Contents/MacOS/ | ||||
cp dep/lib/libcurl.4.dylib $(BUNDLE)/Contents/MacOS/ | cp dep/lib/libcurl.4.dylib $(BUNDLE)/Contents/MacOS/ | ||||
cp dep/lib/libzip.5.dylib $(BUNDLE)/Contents/MacOS/ | cp dep/lib/libzip.5.dylib $(BUNDLE)/Contents/MacOS/ | ||||
<<<<<<< HEAD | |||||
cp dep/lib/librtmidi.4.dylib $(BUNDLE)/Contents/MacOS/ | cp dep/lib/librtmidi.4.dylib $(BUNDLE)/Contents/MacOS/ | ||||
cp dep/lib/librtaudio.dylib $(BUNDLE)/Contents/MacOS/ | cp dep/lib/librtaudio.dylib $(BUNDLE)/Contents/MacOS/ | ||||
======= | |||||
cp dep/lib/librtaudio.dylib $(BUNDLE)/Contents/MacOS/ | |||||
cp dep/lib/librtmidi.4.dylib $(BUNDLE)/Contents/MacOS/ | |||||
cp dep/lib/libcrypto.1.1.dylib $(BUNDLE)/Contents/MacOS/ | |||||
>>>>>>> v0.5 | |||||
install_name_tool -change /usr/local/lib/libGLEW.2.1.0.dylib @executable_path/libGLEW.2.1.0.dylib $(BUNDLE)/Contents/MacOS/Rack | install_name_tool -change /usr/local/lib/libGLEW.2.1.0.dylib @executable_path/libGLEW.2.1.0.dylib $(BUNDLE)/Contents/MacOS/Rack | ||||
install_name_tool -change lib/libglfw.3.dylib @executable_path/libglfw.3.dylib $(BUNDLE)/Contents/MacOS/Rack | install_name_tool -change lib/libglfw.3.dylib @executable_path/libglfw.3.dylib $(BUNDLE)/Contents/MacOS/Rack | ||||
@@ -121,8 +127,14 @@ ifeq ($(ARCH), mac) | |||||
install_name_tool -change $(PWD)/dep/lib/libspeexdsp.1.dylib @executable_path/libspeexdsp.1.dylib $(BUNDLE)/Contents/MacOS/Rack | install_name_tool -change $(PWD)/dep/lib/libspeexdsp.1.dylib @executable_path/libspeexdsp.1.dylib $(BUNDLE)/Contents/MacOS/Rack | ||||
install_name_tool -change $(PWD)/dep/lib/libcurl.4.dylib @executable_path/libcurl.4.dylib $(BUNDLE)/Contents/MacOS/Rack | install_name_tool -change $(PWD)/dep/lib/libcurl.4.dylib @executable_path/libcurl.4.dylib $(BUNDLE)/Contents/MacOS/Rack | ||||
install_name_tool -change $(PWD)/dep/lib/libzip.5.dylib @executable_path/libzip.5.dylib $(BUNDLE)/Contents/MacOS/Rack | install_name_tool -change $(PWD)/dep/lib/libzip.5.dylib @executable_path/libzip.5.dylib $(BUNDLE)/Contents/MacOS/Rack | ||||
<<<<<<< HEAD | |||||
install_name_tool -change $(PWD)/dep/lib/librtmidi.4.dylib @executable_path/librtmidi.4.dylib $(BUNDLE)/Contents/MacOS/Rack | install_name_tool -change $(PWD)/dep/lib/librtmidi.4.dylib @executable_path/librtmidi.4.dylib $(BUNDLE)/Contents/MacOS/Rack | ||||
install_name_tool -change librtaudio.dylib @executable_path/librtaudio.dylib $(BUNDLE)/Contents/MacOS/Rack | install_name_tool -change librtaudio.dylib @executable_path/librtaudio.dylib $(BUNDLE)/Contents/MacOS/Rack | ||||
======= | |||||
install_name_tool -change librtaudio.dylib @executable_path/librtaudio.dylib $(BUNDLE)/Contents/MacOS/Rack | |||||
install_name_tool -change $(PWD)/dep/lib/librtmidi.4.dylib @executable_path/librtmidi.4.dylib $(BUNDLE)/Contents/MacOS/Rack | |||||
install_name_tool -change $(PWD)/dep/lib/libcrypto.1.1.dylib @executable_path/libcrypto.1.1.dylib $(BUNDLE)/Contents/MacOS/Rack | |||||
>>>>>>> v0.5 | |||||
otool -L $(BUNDLE)/Contents/MacOS/Rack | otool -L $(BUNDLE)/Contents/MacOS/Rack | ||||
@@ -149,6 +161,8 @@ ifeq ($(ARCH), win) | |||||
cp dep/bin/libspeexdsp-1.dll dist/Rack/ | cp dep/bin/libspeexdsp-1.dll dist/Rack/ | ||||
cp dep/bin/libzip-5.dll dist/Rack/ | cp dep/bin/libzip-5.dll dist/Rack/ | ||||
cp dep/bin/librtaudio.dll dist/Rack/ | cp dep/bin/librtaudio.dll dist/Rack/ | ||||
cp dep/bin/libcrypto-1_1-x64.dll dist/Rack/ | |||||
cp dep/bin/libssl-1_1-x64.dll dist/Rack/ | |||||
mkdir -p dist/Rack/plugins | mkdir -p dist/Rack/plugins | ||||
cp -R plugins/Fundamental/dist/Fundamental dist/Rack/plugins/ | cp -R plugins/Fundamental/dist/Fundamental dist/Rack/plugins/ | ||||
# Make ZIP | # Make ZIP | ||||
@@ -169,6 +183,8 @@ ifeq ($(ARCH), lin) | |||||
cp dep/lib/libzip.so.5 dist/Rack/ | cp dep/lib/libzip.so.5 dist/Rack/ | ||||
cp dep/lib/librtaudio.so dist/Rack/ | cp dep/lib/librtaudio.so dist/Rack/ | ||||
cp dep/lib/librtmidi.so.4 dist/Rack/ | cp dep/lib/librtmidi.so.4 dist/Rack/ | ||||
cp dep/lib/libssl.so.1.1 dist/Rack/ | |||||
cp dep/lib/libcrypto.so.1.1 dist/Rack/ | |||||
mkdir -p dist/Rack/plugins | mkdir -p dist/Rack/plugins | ||||
cp -R plugins/Fundamental/dist/Fundamental dist/Rack/plugins/ | cp -R plugins/Fundamental/dist/Fundamental dist/Rack/plugins/ | ||||
# Make ZIP | # Make ZIP | ||||
@@ -31,6 +31,7 @@ ifeq ($(ARCH),lin) | |||||
libzip = lib/libzip.so | libzip = lib/libzip.so | ||||
rtmidi = lib/librtmidi.so | rtmidi = lib/librtmidi.so | ||||
rtaudio = lib/librtaudio.so | rtaudio = lib/librtaudio.so | ||||
openssl = lib/libssl.so | |||||
endif | endif | ||||
ifeq ($(ARCH),mac) | ifeq ($(ARCH),mac) | ||||
@@ -42,6 +43,7 @@ ifeq ($(ARCH),mac) | |||||
libzip = lib/libzip.dylib | libzip = lib/libzip.dylib | ||||
rtmidi = lib/librtmidi.dylib | rtmidi = lib/librtmidi.dylib | ||||
rtaudio = lib/librtaudio.dylib | rtaudio = lib/librtaudio.dylib | ||||
openssl = lib/libssl.dylib | |||||
endif | endif | ||||
ifeq ($(ARCH),win) | ifeq ($(ARCH),win) | ||||
@@ -52,7 +54,8 @@ ifeq ($(ARCH),win) | |||||
libcurl = bin/libcurl-4.dll | libcurl = bin/libcurl-4.dll | ||||
libzip = bin/libzip-5.dll | libzip = bin/libzip-5.dll | ||||
rtmidi = bin/librtmidi-4.dll | rtmidi = bin/librtmidi-4.dll | ||||
rtaudio = bin/librtaudio-6.dll | |||||
rtaudio = bin/librtaudio.dll | |||||
openssl = bin/libssl-1_1-x64.dll | |||||
endif | endif | ||||
# Library configuration | # Library configuration | ||||
@@ -106,12 +109,20 @@ $(libspeexdsp): | |||||
$(MAKE) -C speexdsp-SpeexDSP-1.2rc3 | $(MAKE) -C speexdsp-SpeexDSP-1.2rc3 | ||||
$(MAKE) -C speexdsp-SpeexDSP-1.2rc3 install | $(MAKE) -C speexdsp-SpeexDSP-1.2rc3 install | ||||
$(libcurl): | |||||
$(openssl): | |||||
$(WGET) https://www.openssl.org/source/openssl-1.1.0g.tar.gz | |||||
$(UNTAR) openssl-1.1.0g.tar.gz | |||||
cd openssl-1.1.0g && ./config --prefix="$(LOCAL)" | |||||
$(MAKE) -C openssl-1.1.0g | |||||
$(MAKE) -C openssl-1.1.0g install | |||||
$(libcurl): $(openssl) | |||||
$(WGET) https://github.com/curl/curl/releases/download/curl-7_56_0/curl-7.56.0.tar.gz | $(WGET) https://github.com/curl/curl/releases/download/curl-7_56_0/curl-7.56.0.tar.gz | ||||
$(UNTAR) curl-7.56.0.tar.gz | $(UNTAR) curl-7.56.0.tar.gz | ||||
cd curl-7.56.0 && ./configure --prefix="$(LOCAL)" \ | cd curl-7.56.0 && ./configure --prefix="$(LOCAL)" \ | ||||
--disable-ftp --disable-file --disable-ldap --disable-ldaps --disable-rtsp --disable-proxy --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smb --disable-smtp --disable-gopher --disable-manual \ | --disable-ftp --disable-file --disable-ldap --disable-ldaps --disable-rtsp --disable-proxy --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smb --disable-smtp --disable-gopher --disable-manual \ | ||||
--without-zlib --without-ssl --without-ca-bundle --without-ca-path --without-ca-fallback --without-libpsl --without-libmetalink --without-libssh2 --without-librtmp --without-winidn --without-libidn2 --without-nghttp2 | |||||
--without-zlib --without-libpsl --without-libmetalink --without-libssh2 --without-librtmp --without-winidn --without-libidn2 --without-nghttp2 \ | |||||
--without-ca-bundle --with-ca-fallback --with-ssl="$(LOCAL)" | |||||
$(MAKE) -C curl-7.56.0 | $(MAKE) -C curl-7.56.0 | ||||
$(MAKE) -C curl-7.56.0 install | $(MAKE) -C curl-7.56.0 install | ||||
@@ -461,6 +461,14 @@ struct CKSS : SVGSwitch, ToggleSwitch { | |||||
} | } | ||||
}; | }; | ||||
struct CKSSThree : SVGSwitch, ToggleSwitch { | |||||
CKSSThree() { | |||||
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/CKSSThree_0.svg"))); | |||||
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/CKSSThree_1.svg"))); | |||||
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/CKSSThree_2.svg"))); | |||||
} | |||||
}; | |||||
struct CKD6 : SVGSwitch, MomentarySwitch { | struct CKD6 : SVGSwitch, MomentarySwitch { | ||||
CKD6() { | CKD6() { | ||||
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/CKD6_0.svg"))); | addFrame(SVG::load(assetGlobal("res/ComponentLibrary/CKD6_0.svg"))); | ||||
@@ -60,7 +60,8 @@ void pluginInit(); | |||||
void pluginDestroy(); | void pluginDestroy(); | ||||
void pluginLogIn(std::string email, std::string password); | void pluginLogIn(std::string email, std::string password); | ||||
void pluginLogOut(); | void pluginLogOut(); | ||||
void pluginRefresh(); | |||||
/** Returns whether a new plugin is available, and downloads it unless doing a dry run */ | |||||
bool pluginSync(bool dryRun); | |||||
void pluginCancelDownload(); | void pluginCancelDownload(); | ||||
bool pluginIsLoggedIn(); | bool pluginIsLoggedIn(); | ||||
bool pluginIsDownloading(); | bool pluginIsDownloading(); | ||||
@@ -30,6 +30,16 @@ will expand to | |||||
#define LENGTHOF(arr) (sizeof(arr) / sizeof((arr)[0])) | #define LENGTHOF(arr) (sizeof(arr) / sizeof((arr)[0])) | ||||
/** Reserve space for _count enums starting with _name. | |||||
Example: | |||||
enum Foo { | |||||
ENUMS(BAR, 14) | |||||
}; | |||||
BAR + 0 to BAR + 11 is reserved | |||||
*/ | |||||
#define ENUMS(_name, _count) _name, _name ## _LAST = _name + (_count) - 1 | |||||
/** Deprecation notice for GCC */ | /** Deprecation notice for GCC */ | ||||
#define DEPRECATED __attribute__ ((deprecated)) | #define DEPRECATED __attribute__ ((deprecated)) | ||||
@@ -19,5 +19,6 @@ json_t *requestJson(RequestMethod method, std::string url, json_t *dataJ); | |||||
/** Returns the filename, blank if unsuccessful */ | /** Returns the filename, blank if unsuccessful */ | ||||
bool requestDownload(std::string url, std::string filename, float *progress); | bool requestDownload(std::string url, std::string filename, float *progress); | ||||
std::string requestEscape(std::string s); | std::string requestEscape(std::string s); | ||||
std::string requestSHA256File(std::string filename); | |||||
} // namespace rack | } // namespace rack |
@@ -0,0 +1,321 @@ | |||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||||
<!-- Created with Inkscape (http://www.inkscape.org/) --> | |||||
<svg | |||||
xmlns:dc="http://purl.org/dc/elements/1.1/" | |||||
xmlns:cc="http://creativecommons.org/ns#" | |||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |||||
xmlns:svg="http://www.w3.org/2000/svg" | |||||
xmlns="http://www.w3.org/2000/svg" | |||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |||||
width="4.7473302mm" | |||||
height="10.000424mm" | |||||
viewBox="0 0 4.7473302 10.000424" | |||||
version="1.1" | |||||
id="svg258108" | |||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06" | |||||
sodipodi:docname="CKSSThree_0.svg"> | |||||
<defs | |||||
id="defs258102"> | |||||
<linearGradient | |||||
id="linear20" | |||||
gradientUnits="userSpaceOnUse" | |||||
x1="-0.095554203" | |||||
y1="0" | |||||
x2="1.32507" | |||||
y2="0" | |||||
gradientTransform="matrix(0,6.4087959,-6.4087959,0,102.632,66.415358)"> | |||||
<stop | |||||
offset="0" | |||||
style="stop-color:rgb(25.489807%,25.097656%,25.881958%);stop-opacity:1;" | |||||
id="stop217759" /> | |||||
<stop | |||||
offset="0.0625" | |||||
style="stop-color:rgb(25.489807%,25.097656%,25.881958%);stop-opacity:1;" | |||||
id="stop217761" /> | |||||
<stop | |||||
offset="0.078125" | |||||
style="stop-color:rgb(25.398254%,24.996948%,25.778198%);stop-opacity:1;" | |||||
id="stop217763" /> | |||||
<stop | |||||
offset="0.09375" | |||||
style="stop-color:rgb(25.177002%,24.754333%,25.527954%);stop-opacity:1;" | |||||
id="stop217765" /> | |||||
<stop | |||||
offset="0.109375" | |||||
style="stop-color:rgb(24.916077%,24.465942%,25.231934%);stop-opacity:1;" | |||||
id="stop217767" /> | |||||
<stop | |||||
offset="0.125" | |||||
style="stop-color:rgb(24.653625%,24.179077%,24.935913%);stop-opacity:1;" | |||||
id="stop217769" /> | |||||
<stop | |||||
offset="0.140625" | |||||
style="stop-color:rgb(24.3927%,23.892212%,24.639893%);stop-opacity:1;" | |||||
id="stop217771" /> | |||||
<stop | |||||
offset="0.15625" | |||||
style="stop-color:rgb(24.131775%,23.605347%,24.343872%);stop-opacity:1;" | |||||
id="stop217773" /> | |||||
<stop | |||||
offset="0.171875" | |||||
style="stop-color:rgb(23.87085%,23.316956%,24.047852%);stop-opacity:1;" | |||||
id="stop217775" /> | |||||
<stop | |||||
offset="0.1875" | |||||
style="stop-color:rgb(23.609924%,23.03009%,23.751831%);stop-opacity:1;" | |||||
id="stop217777" /> | |||||
<stop | |||||
offset="0.203125" | |||||
style="stop-color:rgb(23.348999%,22.743225%,23.455811%);stop-opacity:1;" | |||||
id="stop217779" /> | |||||
<stop | |||||
offset="0.21875" | |||||
style="stop-color:rgb(23.088074%,22.45636%,23.15979%);stop-opacity:1;" | |||||
id="stop217781" /> | |||||
<stop | |||||
offset="0.234375" | |||||
style="stop-color:rgb(22.825623%,22.167969%,22.86377%);stop-opacity:1;" | |||||
id="stop217783" /> | |||||
<stop | |||||
offset="0.25" | |||||
style="stop-color:rgb(22.564697%,21.881104%,22.567749%);stop-opacity:1;" | |||||
id="stop217785" /> | |||||
<stop | |||||
offset="0.265625" | |||||
style="stop-color:rgb(22.303772%,21.594238%,22.271729%);stop-opacity:1;" | |||||
id="stop217787" /> | |||||
<stop | |||||
offset="0.28125" | |||||
style="stop-color:rgb(22.042847%,21.307373%,21.975708%);stop-opacity:1;" | |||||
id="stop217789" /> | |||||
<stop | |||||
offset="0.296875" | |||||
style="stop-color:rgb(21.781921%,21.018982%,21.679688%);stop-opacity:1;" | |||||
id="stop217791" /> | |||||
<stop | |||||
offset="0.3125" | |||||
style="stop-color:rgb(21.520996%,20.732117%,21.383667%);stop-opacity:1;" | |||||
id="stop217793" /> | |||||
<stop | |||||
offset="0.328125" | |||||
style="stop-color:rgb(21.260071%,20.445251%,21.087646%);stop-opacity:1;" | |||||
id="stop217795" /> | |||||
<stop | |||||
offset="0.34375" | |||||
style="stop-color:rgb(20.99762%,20.15686%,20.793152%);stop-opacity:1;" | |||||
id="stop217797" /> | |||||
<stop | |||||
offset="0.359375" | |||||
style="stop-color:rgb(20.736694%,19.869995%,20.497131%);stop-opacity:1;" | |||||
id="stop217799" /> | |||||
<stop | |||||
offset="0.375" | |||||
style="stop-color:rgb(20.475769%,19.58313%,20.201111%);stop-opacity:1;" | |||||
id="stop217801" /> | |||||
<stop | |||||
offset="0.390625" | |||||
style="stop-color:rgb(20.214844%,19.296265%,19.90509%);stop-opacity:1;" | |||||
id="stop217803" /> | |||||
<stop | |||||
offset="0.40625" | |||||
style="stop-color:rgb(19.953918%,19.007874%,19.60907%);stop-opacity:1;" | |||||
id="stop217805" /> | |||||
<stop | |||||
offset="0.421875" | |||||
style="stop-color:rgb(19.692993%,18.721008%,19.313049%);stop-opacity:1;" | |||||
id="stop217807" /> | |||||
<stop | |||||
offset="0.4375" | |||||
style="stop-color:rgb(19.432068%,18.434143%,19.017029%);stop-opacity:1;" | |||||
id="stop217809" /> | |||||
<stop | |||||
offset="0.453125" | |||||
style="stop-color:rgb(19.169617%,18.147278%,18.721008%);stop-opacity:1;" | |||||
id="stop217811" /> | |||||
<stop | |||||
offset="0.46875" | |||||
style="stop-color:rgb(18.908691%,17.858887%,18.424988%);stop-opacity:1;" | |||||
id="stop217813" /> | |||||
<stop | |||||
offset="0.484375" | |||||
style="stop-color:rgb(18.647766%,17.572021%,18.128967%);stop-opacity:1;" | |||||
id="stop217815" /> | |||||
<stop | |||||
offset="0.5" | |||||
style="stop-color:rgb(18.386841%,17.285156%,17.832947%);stop-opacity:1;" | |||||
id="stop217817" /> | |||||
<stop | |||||
offset="0.515625" | |||||
style="stop-color:rgb(18.125916%,16.998291%,17.536926%);stop-opacity:1;" | |||||
id="stop217819" /> | |||||
<stop | |||||
offset="0.53125" | |||||
style="stop-color:rgb(17.86499%,16.7099%,17.240906%);stop-opacity:1;" | |||||
id="stop217821" /> | |||||
<stop | |||||
offset="0.546875" | |||||
style="stop-color:rgb(17.604065%,16.423035%,16.944885%);stop-opacity:1;" | |||||
id="stop217823" /> | |||||
<stop | |||||
offset="0.5625" | |||||
style="stop-color:rgb(17.341614%,16.136169%,16.648865%);stop-opacity:1;" | |||||
id="stop217825" /> | |||||
<stop | |||||
offset="0.578125" | |||||
style="stop-color:rgb(17.080688%,15.849304%,16.352844%);stop-opacity:1;" | |||||
id="stop217827" /> | |||||
<stop | |||||
offset="0.59375" | |||||
style="stop-color:rgb(16.819763%,15.560913%,16.056824%);stop-opacity:1;" | |||||
id="stop217829" /> | |||||
<stop | |||||
offset="0.609375" | |||||
style="stop-color:rgb(16.558838%,15.274048%,15.760803%);stop-opacity:1;" | |||||
id="stop217831" /> | |||||
<stop | |||||
offset="0.625" | |||||
style="stop-color:rgb(16.297913%,14.987183%,15.464783%);stop-opacity:1;" | |||||
id="stop217833" /> | |||||
<stop | |||||
offset="0.640625" | |||||
style="stop-color:rgb(16.036987%,14.700317%,15.168762%);stop-opacity:1;" | |||||
id="stop217835" /> | |||||
<stop | |||||
offset="0.65625" | |||||
style="stop-color:rgb(15.776062%,14.411926%,14.872742%);stop-opacity:1;" | |||||
id="stop217837" /> | |||||
<stop | |||||
offset="0.671875" | |||||
style="stop-color:rgb(15.513611%,14.125061%,14.576721%);stop-opacity:1;" | |||||
id="stop217839" /> | |||||
<stop | |||||
offset="0.6875" | |||||
style="stop-color:rgb(15.252686%,13.838196%,14.280701%);stop-opacity:1;" | |||||
id="stop217841" /> | |||||
<stop | |||||
offset="0.703125" | |||||
style="stop-color:rgb(14.99176%,13.551331%,13.98468%);stop-opacity:1;" | |||||
id="stop217843" /> | |||||
<stop | |||||
offset="0.71875" | |||||
style="stop-color:rgb(14.730835%,13.262939%,13.68866%);stop-opacity:1;" | |||||
id="stop217845" /> | |||||
<stop | |||||
offset="0.734375" | |||||
style="stop-color:rgb(14.46991%,12.976074%,13.392639%);stop-opacity:1;" | |||||
id="stop217847" /> | |||||
<stop | |||||
offset="0.75" | |||||
style="stop-color:rgb(14.208984%,12.689209%,13.096619%);stop-opacity:1;" | |||||
id="stop217849" /> | |||||
<stop | |||||
offset="0.765625" | |||||
style="stop-color:rgb(13.948059%,12.402344%,12.802124%);stop-opacity:1;" | |||||
id="stop217851" /> | |||||
<stop | |||||
offset="0.78125" | |||||
style="stop-color:rgb(13.771057%,12.207031%,12.600708%);stop-opacity:1;" | |||||
id="stop217853" /> | |||||
<stop | |||||
offset="0.8125" | |||||
style="stop-color:rgb(13.725281%,12.156677%,12.548828%);stop-opacity:1;" | |||||
id="stop217855" /> | |||||
<stop | |||||
offset="0.875" | |||||
style="stop-color:rgb(13.725281%,12.156677%,12.548828%);stop-opacity:1;" | |||||
id="stop217857" /> | |||||
<stop | |||||
offset="1" | |||||
style="stop-color:rgb(13.725281%,12.156677%,12.548828%);stop-opacity:1;" | |||||
id="stop217859" /> | |||||
</linearGradient> | |||||
</defs> | |||||
<sodipodi:namedview | |||||
id="base" | |||||
pagecolor="#ffffff" | |||||
bordercolor="#666666" | |||||
borderopacity="1.0" | |||||
inkscape:pageopacity="0.0" | |||||
inkscape:pageshadow="2" | |||||
inkscape:zoom="11.2" | |||||
inkscape:cx="10.029443" | |||||
inkscape:cy="16.956782" | |||||
inkscape:document-units="mm" | |||||
inkscape:current-layer="g258244" | |||||
showgrid="false" | |||||
fit-margin-top="0" | |||||
fit-margin-left="0" | |||||
fit-margin-right="0" | |||||
fit-margin-bottom="0" | |||||
inkscape:window-width="1600" | |||||
inkscape:window-height="882" | |||||
inkscape:window-x="0" | |||||
inkscape:window-y="18" | |||||
inkscape:window-maximized="0" /> | |||||
<metadata | |||||
id="metadata258105"> | |||||
<rdf:RDF> | |||||
<cc:Work | |||||
rdf:about=""> | |||||
<dc:format>image/svg+xml</dc:format> | |||||
<dc:type | |||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | |||||
<dc:title></dc:title> | |||||
</cc:Work> | |||||
</rdf:RDF> | |||||
</metadata> | |||||
<g | |||||
inkscape:label="Layer 1" | |||||
inkscape:groupmode="layer" | |||||
id="layer1" | |||||
transform="translate(-100.25783,-65.355229)"> | |||||
<g | |||||
id="g258244"> | |||||
<path | |||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.25783,65.855457 c 0,-0.275608 0.22599,-0.500228 0.50021,-0.500228 h 3.74826 c 0.27425,0 0.49886,0.22462 0.49886,0.500228 v 8.999967 c 0,0.274229 -0.22461,0.500229 -0.49886,0.500229 h -3.74826 c -0.27422,0 -0.50021,-0.226 -0.50021,-0.500229 z m 0,0" | |||||
id="path243332" | |||||
inkscape:connector-curvature="0" /> | |||||
<path | |||||
style="clip-rule:nonzero;fill:#414042;fill-rule:nonzero;stroke:none;stroke-width:0.35277775;fill-opacity:1" | |||||
d="m 104.56144,65.803091 h -3.85851 v 9.1047 h 3.85851 z m 0,0" | |||||
id="path243334" | |||||
inkscape:connector-curvature="0" /> | |||||
</g> | |||||
<g | |||||
id="g258240"> | |||||
<path | |||||
style="fill:#424242;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.70156,71.907801 h 3.85988 v 2.99999 h -3.85988 z m 0,0" | |||||
id="path243340" | |||||
inkscape:connector-curvature="0" /> | |||||
<path | |||||
style="fill:#979797;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.70156,73.241742 h 3.85988 v 0.330729 h -3.85988 z m 0,0" | |||||
id="path243342" | |||||
inkscape:connector-curvature="0" /> | |||||
<path | |||||
style="fill:#979797;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.70156,74.577062 h 3.85988 v 0.330729 h -3.85988 z m 0,0" | |||||
id="path243344" | |||||
inkscape:connector-curvature="0" /> | |||||
<path | |||||
style="fill:#979797;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.70156,73.91009 h 3.85988 v 0.330729 h -3.85988 z m 0,0" | |||||
id="path243346" | |||||
inkscape:connector-curvature="0" /> | |||||
<path | |||||
style="fill:#979797;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.70156,72.574773 h 3.85988 v 0.330729 h -3.85988 z m 0,0" | |||||
id="path243348" | |||||
inkscape:connector-curvature="0" /> | |||||
<path | |||||
style="fill:#979797;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.70156,71.907801 h 3.85988 v 0.329349 h -3.85988 z m 0,0" | |||||
id="path243350" | |||||
inkscape:connector-curvature="0" /> | |||||
</g> | |||||
</g> | |||||
</svg> |
@@ -0,0 +1,322 @@ | |||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||||
<!-- Created with Inkscape (http://www.inkscape.org/) --> | |||||
<svg | |||||
xmlns:dc="http://purl.org/dc/elements/1.1/" | |||||
xmlns:cc="http://creativecommons.org/ns#" | |||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |||||
xmlns:svg="http://www.w3.org/2000/svg" | |||||
xmlns="http://www.w3.org/2000/svg" | |||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |||||
width="4.7473302mm" | |||||
height="10.000424mm" | |||||
viewBox="0 0 4.7473302 10.000424" | |||||
version="1.1" | |||||
id="svg258108" | |||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06" | |||||
sodipodi:docname="CKSSThree_1.svg"> | |||||
<defs | |||||
id="defs258102"> | |||||
<linearGradient | |||||
id="linear20" | |||||
gradientUnits="userSpaceOnUse" | |||||
x1="-0.095554203" | |||||
y1="0" | |||||
x2="1.32507" | |||||
y2="0" | |||||
gradientTransform="matrix(0,6.4087959,-6.4087959,0,102.632,66.415358)"> | |||||
<stop | |||||
offset="0" | |||||
style="stop-color:rgb(25.489807%,25.097656%,25.881958%);stop-opacity:1;" | |||||
id="stop217759" /> | |||||
<stop | |||||
offset="0.0625" | |||||
style="stop-color:rgb(25.489807%,25.097656%,25.881958%);stop-opacity:1;" | |||||
id="stop217761" /> | |||||
<stop | |||||
offset="0.078125" | |||||
style="stop-color:rgb(25.398254%,24.996948%,25.778198%);stop-opacity:1;" | |||||
id="stop217763" /> | |||||
<stop | |||||
offset="0.09375" | |||||
style="stop-color:rgb(25.177002%,24.754333%,25.527954%);stop-opacity:1;" | |||||
id="stop217765" /> | |||||
<stop | |||||
offset="0.109375" | |||||
style="stop-color:rgb(24.916077%,24.465942%,25.231934%);stop-opacity:1;" | |||||
id="stop217767" /> | |||||
<stop | |||||
offset="0.125" | |||||
style="stop-color:rgb(24.653625%,24.179077%,24.935913%);stop-opacity:1;" | |||||
id="stop217769" /> | |||||
<stop | |||||
offset="0.140625" | |||||
style="stop-color:rgb(24.3927%,23.892212%,24.639893%);stop-opacity:1;" | |||||
id="stop217771" /> | |||||
<stop | |||||
offset="0.15625" | |||||
style="stop-color:rgb(24.131775%,23.605347%,24.343872%);stop-opacity:1;" | |||||
id="stop217773" /> | |||||
<stop | |||||
offset="0.171875" | |||||
style="stop-color:rgb(23.87085%,23.316956%,24.047852%);stop-opacity:1;" | |||||
id="stop217775" /> | |||||
<stop | |||||
offset="0.1875" | |||||
style="stop-color:rgb(23.609924%,23.03009%,23.751831%);stop-opacity:1;" | |||||
id="stop217777" /> | |||||
<stop | |||||
offset="0.203125" | |||||
style="stop-color:rgb(23.348999%,22.743225%,23.455811%);stop-opacity:1;" | |||||
id="stop217779" /> | |||||
<stop | |||||
offset="0.21875" | |||||
style="stop-color:rgb(23.088074%,22.45636%,23.15979%);stop-opacity:1;" | |||||
id="stop217781" /> | |||||
<stop | |||||
offset="0.234375" | |||||
style="stop-color:rgb(22.825623%,22.167969%,22.86377%);stop-opacity:1;" | |||||
id="stop217783" /> | |||||
<stop | |||||
offset="0.25" | |||||
style="stop-color:rgb(22.564697%,21.881104%,22.567749%);stop-opacity:1;" | |||||
id="stop217785" /> | |||||
<stop | |||||
offset="0.265625" | |||||
style="stop-color:rgb(22.303772%,21.594238%,22.271729%);stop-opacity:1;" | |||||
id="stop217787" /> | |||||
<stop | |||||
offset="0.28125" | |||||
style="stop-color:rgb(22.042847%,21.307373%,21.975708%);stop-opacity:1;" | |||||
id="stop217789" /> | |||||
<stop | |||||
offset="0.296875" | |||||
style="stop-color:rgb(21.781921%,21.018982%,21.679688%);stop-opacity:1;" | |||||
id="stop217791" /> | |||||
<stop | |||||
offset="0.3125" | |||||
style="stop-color:rgb(21.520996%,20.732117%,21.383667%);stop-opacity:1;" | |||||
id="stop217793" /> | |||||
<stop | |||||
offset="0.328125" | |||||
style="stop-color:rgb(21.260071%,20.445251%,21.087646%);stop-opacity:1;" | |||||
id="stop217795" /> | |||||
<stop | |||||
offset="0.34375" | |||||
style="stop-color:rgb(20.99762%,20.15686%,20.793152%);stop-opacity:1;" | |||||
id="stop217797" /> | |||||
<stop | |||||
offset="0.359375" | |||||
style="stop-color:rgb(20.736694%,19.869995%,20.497131%);stop-opacity:1;" | |||||
id="stop217799" /> | |||||
<stop | |||||
offset="0.375" | |||||
style="stop-color:rgb(20.475769%,19.58313%,20.201111%);stop-opacity:1;" | |||||
id="stop217801" /> | |||||
<stop | |||||
offset="0.390625" | |||||
style="stop-color:rgb(20.214844%,19.296265%,19.90509%);stop-opacity:1;" | |||||
id="stop217803" /> | |||||
<stop | |||||
offset="0.40625" | |||||
style="stop-color:rgb(19.953918%,19.007874%,19.60907%);stop-opacity:1;" | |||||
id="stop217805" /> | |||||
<stop | |||||
offset="0.421875" | |||||
style="stop-color:rgb(19.692993%,18.721008%,19.313049%);stop-opacity:1;" | |||||
id="stop217807" /> | |||||
<stop | |||||
offset="0.4375" | |||||
style="stop-color:rgb(19.432068%,18.434143%,19.017029%);stop-opacity:1;" | |||||
id="stop217809" /> | |||||
<stop | |||||
offset="0.453125" | |||||
style="stop-color:rgb(19.169617%,18.147278%,18.721008%);stop-opacity:1;" | |||||
id="stop217811" /> | |||||
<stop | |||||
offset="0.46875" | |||||
style="stop-color:rgb(18.908691%,17.858887%,18.424988%);stop-opacity:1;" | |||||
id="stop217813" /> | |||||
<stop | |||||
offset="0.484375" | |||||
style="stop-color:rgb(18.647766%,17.572021%,18.128967%);stop-opacity:1;" | |||||
id="stop217815" /> | |||||
<stop | |||||
offset="0.5" | |||||
style="stop-color:rgb(18.386841%,17.285156%,17.832947%);stop-opacity:1;" | |||||
id="stop217817" /> | |||||
<stop | |||||
offset="0.515625" | |||||
style="stop-color:rgb(18.125916%,16.998291%,17.536926%);stop-opacity:1;" | |||||
id="stop217819" /> | |||||
<stop | |||||
offset="0.53125" | |||||
style="stop-color:rgb(17.86499%,16.7099%,17.240906%);stop-opacity:1;" | |||||
id="stop217821" /> | |||||
<stop | |||||
offset="0.546875" | |||||
style="stop-color:rgb(17.604065%,16.423035%,16.944885%);stop-opacity:1;" | |||||
id="stop217823" /> | |||||
<stop | |||||
offset="0.5625" | |||||
style="stop-color:rgb(17.341614%,16.136169%,16.648865%);stop-opacity:1;" | |||||
id="stop217825" /> | |||||
<stop | |||||
offset="0.578125" | |||||
style="stop-color:rgb(17.080688%,15.849304%,16.352844%);stop-opacity:1;" | |||||
id="stop217827" /> | |||||
<stop | |||||
offset="0.59375" | |||||
style="stop-color:rgb(16.819763%,15.560913%,16.056824%);stop-opacity:1;" | |||||
id="stop217829" /> | |||||
<stop | |||||
offset="0.609375" | |||||
style="stop-color:rgb(16.558838%,15.274048%,15.760803%);stop-opacity:1;" | |||||
id="stop217831" /> | |||||
<stop | |||||
offset="0.625" | |||||
style="stop-color:rgb(16.297913%,14.987183%,15.464783%);stop-opacity:1;" | |||||
id="stop217833" /> | |||||
<stop | |||||
offset="0.640625" | |||||
style="stop-color:rgb(16.036987%,14.700317%,15.168762%);stop-opacity:1;" | |||||
id="stop217835" /> | |||||
<stop | |||||
offset="0.65625" | |||||
style="stop-color:rgb(15.776062%,14.411926%,14.872742%);stop-opacity:1;" | |||||
id="stop217837" /> | |||||
<stop | |||||
offset="0.671875" | |||||
style="stop-color:rgb(15.513611%,14.125061%,14.576721%);stop-opacity:1;" | |||||
id="stop217839" /> | |||||
<stop | |||||
offset="0.6875" | |||||
style="stop-color:rgb(15.252686%,13.838196%,14.280701%);stop-opacity:1;" | |||||
id="stop217841" /> | |||||
<stop | |||||
offset="0.703125" | |||||
style="stop-color:rgb(14.99176%,13.551331%,13.98468%);stop-opacity:1;" | |||||
id="stop217843" /> | |||||
<stop | |||||
offset="0.71875" | |||||
style="stop-color:rgb(14.730835%,13.262939%,13.68866%);stop-opacity:1;" | |||||
id="stop217845" /> | |||||
<stop | |||||
offset="0.734375" | |||||
style="stop-color:rgb(14.46991%,12.976074%,13.392639%);stop-opacity:1;" | |||||
id="stop217847" /> | |||||
<stop | |||||
offset="0.75" | |||||
style="stop-color:rgb(14.208984%,12.689209%,13.096619%);stop-opacity:1;" | |||||
id="stop217849" /> | |||||
<stop | |||||
offset="0.765625" | |||||
style="stop-color:rgb(13.948059%,12.402344%,12.802124%);stop-opacity:1;" | |||||
id="stop217851" /> | |||||
<stop | |||||
offset="0.78125" | |||||
style="stop-color:rgb(13.771057%,12.207031%,12.600708%);stop-opacity:1;" | |||||
id="stop217853" /> | |||||
<stop | |||||
offset="0.8125" | |||||
style="stop-color:rgb(13.725281%,12.156677%,12.548828%);stop-opacity:1;" | |||||
id="stop217855" /> | |||||
<stop | |||||
offset="0.875" | |||||
style="stop-color:rgb(13.725281%,12.156677%,12.548828%);stop-opacity:1;" | |||||
id="stop217857" /> | |||||
<stop | |||||
offset="1" | |||||
style="stop-color:rgb(13.725281%,12.156677%,12.548828%);stop-opacity:1;" | |||||
id="stop217859" /> | |||||
</linearGradient> | |||||
</defs> | |||||
<sodipodi:namedview | |||||
id="base" | |||||
pagecolor="#ffffff" | |||||
bordercolor="#666666" | |||||
borderopacity="1.0" | |||||
inkscape:pageopacity="0.0" | |||||
inkscape:pageshadow="2" | |||||
inkscape:zoom="11.2" | |||||
inkscape:cx="10.922301" | |||||
inkscape:cy="16.956782" | |||||
inkscape:document-units="mm" | |||||
inkscape:current-layer="layer1" | |||||
showgrid="false" | |||||
fit-margin-top="0" | |||||
fit-margin-left="0" | |||||
fit-margin-right="0" | |||||
fit-margin-bottom="0" | |||||
inkscape:window-width="1600" | |||||
inkscape:window-height="882" | |||||
inkscape:window-x="0" | |||||
inkscape:window-y="18" | |||||
inkscape:window-maximized="0" /> | |||||
<metadata | |||||
id="metadata258105"> | |||||
<rdf:RDF> | |||||
<cc:Work | |||||
rdf:about=""> | |||||
<dc:format>image/svg+xml</dc:format> | |||||
<dc:type | |||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | |||||
<dc:title></dc:title> | |||||
</cc:Work> | |||||
</rdf:RDF> | |||||
</metadata> | |||||
<g | |||||
inkscape:label="Layer 1" | |||||
inkscape:groupmode="layer" | |||||
id="layer1" | |||||
transform="translate(-100.25783,-65.355229)"> | |||||
<g | |||||
id="g258244"> | |||||
<path | |||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.25783,65.855457 c 0,-0.275608 0.22599,-0.500228 0.50021,-0.500228 h 3.74826 c 0.27425,0 0.49886,0.22462 0.49886,0.500228 v 8.999967 c 0,0.274229 -0.22461,0.500229 -0.49886,0.500229 h -3.74826 c -0.27422,0 -0.50021,-0.226 -0.50021,-0.500229 z m 0,0" | |||||
id="path243332" | |||||
inkscape:connector-curvature="0" /> | |||||
<path | |||||
style="clip-rule:nonzero;fill:#414042;fill-rule:nonzero;stroke:none;stroke-width:0.35277775;fill-opacity:1" | |||||
d="m 104.56144,65.803091 h -3.85851 v 9.1047 h 3.85851 z m 0,0" | |||||
id="path243334" | |||||
inkscape:connector-curvature="0" /> | |||||
</g> | |||||
<g | |||||
id="g258240" | |||||
transform="translate(0,-3.0523548)"> | |||||
<path | |||||
style="fill:#424242;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.70156,71.907801 h 3.85988 v 2.99999 h -3.85988 z m 0,0" | |||||
id="path243340" | |||||
inkscape:connector-curvature="0" /> | |||||
<path | |||||
style="fill:#979797;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.70156,73.241742 h 3.85988 v 0.330729 h -3.85988 z m 0,0" | |||||
id="path243342" | |||||
inkscape:connector-curvature="0" /> | |||||
<path | |||||
style="fill:#979797;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.70156,74.577062 h 3.85988 v 0.330729 h -3.85988 z m 0,0" | |||||
id="path243344" | |||||
inkscape:connector-curvature="0" /> | |||||
<path | |||||
style="fill:#979797;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.70156,73.91009 h 3.85988 v 0.330729 h -3.85988 z m 0,0" | |||||
id="path243346" | |||||
inkscape:connector-curvature="0" /> | |||||
<path | |||||
style="fill:#979797;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.70156,72.574773 h 3.85988 v 0.330729 h -3.85988 z m 0,0" | |||||
id="path243348" | |||||
inkscape:connector-curvature="0" /> | |||||
<path | |||||
style="fill:#979797;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.70156,71.907801 h 3.85988 v 0.329349 h -3.85988 z m 0,0" | |||||
id="path243350" | |||||
inkscape:connector-curvature="0" /> | |||||
</g> | |||||
</g> | |||||
</svg> |
@@ -0,0 +1,322 @@ | |||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||||
<!-- Created with Inkscape (http://www.inkscape.org/) --> | |||||
<svg | |||||
xmlns:dc="http://purl.org/dc/elements/1.1/" | |||||
xmlns:cc="http://creativecommons.org/ns#" | |||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |||||
xmlns:svg="http://www.w3.org/2000/svg" | |||||
xmlns="http://www.w3.org/2000/svg" | |||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |||||
width="4.7473302mm" | |||||
height="10.000424mm" | |||||
viewBox="0 0 4.7473302 10.000424" | |||||
version="1.1" | |||||
id="svg258108" | |||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06" | |||||
sodipodi:docname="CKSSThree_2.svg"> | |||||
<defs | |||||
id="defs258102"> | |||||
<linearGradient | |||||
id="linear20" | |||||
gradientUnits="userSpaceOnUse" | |||||
x1="-0.095554203" | |||||
y1="0" | |||||
x2="1.32507" | |||||
y2="0" | |||||
gradientTransform="matrix(0,6.4087959,-6.4087959,0,102.632,66.415358)"> | |||||
<stop | |||||
offset="0" | |||||
style="stop-color:rgb(25.489807%,25.097656%,25.881958%);stop-opacity:1;" | |||||
id="stop217759" /> | |||||
<stop | |||||
offset="0.0625" | |||||
style="stop-color:rgb(25.489807%,25.097656%,25.881958%);stop-opacity:1;" | |||||
id="stop217761" /> | |||||
<stop | |||||
offset="0.078125" | |||||
style="stop-color:rgb(25.398254%,24.996948%,25.778198%);stop-opacity:1;" | |||||
id="stop217763" /> | |||||
<stop | |||||
offset="0.09375" | |||||
style="stop-color:rgb(25.177002%,24.754333%,25.527954%);stop-opacity:1;" | |||||
id="stop217765" /> | |||||
<stop | |||||
offset="0.109375" | |||||
style="stop-color:rgb(24.916077%,24.465942%,25.231934%);stop-opacity:1;" | |||||
id="stop217767" /> | |||||
<stop | |||||
offset="0.125" | |||||
style="stop-color:rgb(24.653625%,24.179077%,24.935913%);stop-opacity:1;" | |||||
id="stop217769" /> | |||||
<stop | |||||
offset="0.140625" | |||||
style="stop-color:rgb(24.3927%,23.892212%,24.639893%);stop-opacity:1;" | |||||
id="stop217771" /> | |||||
<stop | |||||
offset="0.15625" | |||||
style="stop-color:rgb(24.131775%,23.605347%,24.343872%);stop-opacity:1;" | |||||
id="stop217773" /> | |||||
<stop | |||||
offset="0.171875" | |||||
style="stop-color:rgb(23.87085%,23.316956%,24.047852%);stop-opacity:1;" | |||||
id="stop217775" /> | |||||
<stop | |||||
offset="0.1875" | |||||
style="stop-color:rgb(23.609924%,23.03009%,23.751831%);stop-opacity:1;" | |||||
id="stop217777" /> | |||||
<stop | |||||
offset="0.203125" | |||||
style="stop-color:rgb(23.348999%,22.743225%,23.455811%);stop-opacity:1;" | |||||
id="stop217779" /> | |||||
<stop | |||||
offset="0.21875" | |||||
style="stop-color:rgb(23.088074%,22.45636%,23.15979%);stop-opacity:1;" | |||||
id="stop217781" /> | |||||
<stop | |||||
offset="0.234375" | |||||
style="stop-color:rgb(22.825623%,22.167969%,22.86377%);stop-opacity:1;" | |||||
id="stop217783" /> | |||||
<stop | |||||
offset="0.25" | |||||
style="stop-color:rgb(22.564697%,21.881104%,22.567749%);stop-opacity:1;" | |||||
id="stop217785" /> | |||||
<stop | |||||
offset="0.265625" | |||||
style="stop-color:rgb(22.303772%,21.594238%,22.271729%);stop-opacity:1;" | |||||
id="stop217787" /> | |||||
<stop | |||||
offset="0.28125" | |||||
style="stop-color:rgb(22.042847%,21.307373%,21.975708%);stop-opacity:1;" | |||||
id="stop217789" /> | |||||
<stop | |||||
offset="0.296875" | |||||
style="stop-color:rgb(21.781921%,21.018982%,21.679688%);stop-opacity:1;" | |||||
id="stop217791" /> | |||||
<stop | |||||
offset="0.3125" | |||||
style="stop-color:rgb(21.520996%,20.732117%,21.383667%);stop-opacity:1;" | |||||
id="stop217793" /> | |||||
<stop | |||||
offset="0.328125" | |||||
style="stop-color:rgb(21.260071%,20.445251%,21.087646%);stop-opacity:1;" | |||||
id="stop217795" /> | |||||
<stop | |||||
offset="0.34375" | |||||
style="stop-color:rgb(20.99762%,20.15686%,20.793152%);stop-opacity:1;" | |||||
id="stop217797" /> | |||||
<stop | |||||
offset="0.359375" | |||||
style="stop-color:rgb(20.736694%,19.869995%,20.497131%);stop-opacity:1;" | |||||
id="stop217799" /> | |||||
<stop | |||||
offset="0.375" | |||||
style="stop-color:rgb(20.475769%,19.58313%,20.201111%);stop-opacity:1;" | |||||
id="stop217801" /> | |||||
<stop | |||||
offset="0.390625" | |||||
style="stop-color:rgb(20.214844%,19.296265%,19.90509%);stop-opacity:1;" | |||||
id="stop217803" /> | |||||
<stop | |||||
offset="0.40625" | |||||
style="stop-color:rgb(19.953918%,19.007874%,19.60907%);stop-opacity:1;" | |||||
id="stop217805" /> | |||||
<stop | |||||
offset="0.421875" | |||||
style="stop-color:rgb(19.692993%,18.721008%,19.313049%);stop-opacity:1;" | |||||
id="stop217807" /> | |||||
<stop | |||||
offset="0.4375" | |||||
style="stop-color:rgb(19.432068%,18.434143%,19.017029%);stop-opacity:1;" | |||||
id="stop217809" /> | |||||
<stop | |||||
offset="0.453125" | |||||
style="stop-color:rgb(19.169617%,18.147278%,18.721008%);stop-opacity:1;" | |||||
id="stop217811" /> | |||||
<stop | |||||
offset="0.46875" | |||||
style="stop-color:rgb(18.908691%,17.858887%,18.424988%);stop-opacity:1;" | |||||
id="stop217813" /> | |||||
<stop | |||||
offset="0.484375" | |||||
style="stop-color:rgb(18.647766%,17.572021%,18.128967%);stop-opacity:1;" | |||||
id="stop217815" /> | |||||
<stop | |||||
offset="0.5" | |||||
style="stop-color:rgb(18.386841%,17.285156%,17.832947%);stop-opacity:1;" | |||||
id="stop217817" /> | |||||
<stop | |||||
offset="0.515625" | |||||
style="stop-color:rgb(18.125916%,16.998291%,17.536926%);stop-opacity:1;" | |||||
id="stop217819" /> | |||||
<stop | |||||
offset="0.53125" | |||||
style="stop-color:rgb(17.86499%,16.7099%,17.240906%);stop-opacity:1;" | |||||
id="stop217821" /> | |||||
<stop | |||||
offset="0.546875" | |||||
style="stop-color:rgb(17.604065%,16.423035%,16.944885%);stop-opacity:1;" | |||||
id="stop217823" /> | |||||
<stop | |||||
offset="0.5625" | |||||
style="stop-color:rgb(17.341614%,16.136169%,16.648865%);stop-opacity:1;" | |||||
id="stop217825" /> | |||||
<stop | |||||
offset="0.578125" | |||||
style="stop-color:rgb(17.080688%,15.849304%,16.352844%);stop-opacity:1;" | |||||
id="stop217827" /> | |||||
<stop | |||||
offset="0.59375" | |||||
style="stop-color:rgb(16.819763%,15.560913%,16.056824%);stop-opacity:1;" | |||||
id="stop217829" /> | |||||
<stop | |||||
offset="0.609375" | |||||
style="stop-color:rgb(16.558838%,15.274048%,15.760803%);stop-opacity:1;" | |||||
id="stop217831" /> | |||||
<stop | |||||
offset="0.625" | |||||
style="stop-color:rgb(16.297913%,14.987183%,15.464783%);stop-opacity:1;" | |||||
id="stop217833" /> | |||||
<stop | |||||
offset="0.640625" | |||||
style="stop-color:rgb(16.036987%,14.700317%,15.168762%);stop-opacity:1;" | |||||
id="stop217835" /> | |||||
<stop | |||||
offset="0.65625" | |||||
style="stop-color:rgb(15.776062%,14.411926%,14.872742%);stop-opacity:1;" | |||||
id="stop217837" /> | |||||
<stop | |||||
offset="0.671875" | |||||
style="stop-color:rgb(15.513611%,14.125061%,14.576721%);stop-opacity:1;" | |||||
id="stop217839" /> | |||||
<stop | |||||
offset="0.6875" | |||||
style="stop-color:rgb(15.252686%,13.838196%,14.280701%);stop-opacity:1;" | |||||
id="stop217841" /> | |||||
<stop | |||||
offset="0.703125" | |||||
style="stop-color:rgb(14.99176%,13.551331%,13.98468%);stop-opacity:1;" | |||||
id="stop217843" /> | |||||
<stop | |||||
offset="0.71875" | |||||
style="stop-color:rgb(14.730835%,13.262939%,13.68866%);stop-opacity:1;" | |||||
id="stop217845" /> | |||||
<stop | |||||
offset="0.734375" | |||||
style="stop-color:rgb(14.46991%,12.976074%,13.392639%);stop-opacity:1;" | |||||
id="stop217847" /> | |||||
<stop | |||||
offset="0.75" | |||||
style="stop-color:rgb(14.208984%,12.689209%,13.096619%);stop-opacity:1;" | |||||
id="stop217849" /> | |||||
<stop | |||||
offset="0.765625" | |||||
style="stop-color:rgb(13.948059%,12.402344%,12.802124%);stop-opacity:1;" | |||||
id="stop217851" /> | |||||
<stop | |||||
offset="0.78125" | |||||
style="stop-color:rgb(13.771057%,12.207031%,12.600708%);stop-opacity:1;" | |||||
id="stop217853" /> | |||||
<stop | |||||
offset="0.8125" | |||||
style="stop-color:rgb(13.725281%,12.156677%,12.548828%);stop-opacity:1;" | |||||
id="stop217855" /> | |||||
<stop | |||||
offset="0.875" | |||||
style="stop-color:rgb(13.725281%,12.156677%,12.548828%);stop-opacity:1;" | |||||
id="stop217857" /> | |||||
<stop | |||||
offset="1" | |||||
style="stop-color:rgb(13.725281%,12.156677%,12.548828%);stop-opacity:1;" | |||||
id="stop217859" /> | |||||
</linearGradient> | |||||
</defs> | |||||
<sodipodi:namedview | |||||
id="base" | |||||
pagecolor="#ffffff" | |||||
bordercolor="#666666" | |||||
borderopacity="1.0" | |||||
inkscape:pageopacity="0.0" | |||||
inkscape:pageshadow="2" | |||||
inkscape:zoom="11.2" | |||||
inkscape:cx="10.922301" | |||||
inkscape:cy="16.956782" | |||||
inkscape:document-units="mm" | |||||
inkscape:current-layer="layer1" | |||||
showgrid="false" | |||||
fit-margin-top="0" | |||||
fit-margin-left="0" | |||||
fit-margin-right="0" | |||||
fit-margin-bottom="0" | |||||
inkscape:window-width="1600" | |||||
inkscape:window-height="882" | |||||
inkscape:window-x="0" | |||||
inkscape:window-y="18" | |||||
inkscape:window-maximized="0" /> | |||||
<metadata | |||||
id="metadata258105"> | |||||
<rdf:RDF> | |||||
<cc:Work | |||||
rdf:about=""> | |||||
<dc:format>image/svg+xml</dc:format> | |||||
<dc:type | |||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | |||||
<dc:title></dc:title> | |||||
</cc:Work> | |||||
</rdf:RDF> | |||||
</metadata> | |||||
<g | |||||
inkscape:label="Layer 1" | |||||
inkscape:groupmode="layer" | |||||
id="layer1" | |||||
transform="translate(-100.25783,-65.355229)"> | |||||
<g | |||||
id="g258244"> | |||||
<path | |||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.25783,65.855457 c 0,-0.275608 0.22599,-0.500228 0.50021,-0.500228 h 3.74826 c 0.27425,0 0.49886,0.22462 0.49886,0.500228 v 8.999967 c 0,0.274229 -0.22461,0.500229 -0.49886,0.500229 h -3.74826 c -0.27422,0 -0.50021,-0.226 -0.50021,-0.500229 z m 0,0" | |||||
id="path243332" | |||||
inkscape:connector-curvature="0" /> | |||||
<path | |||||
style="clip-rule:nonzero;fill:#414042;fill-rule:nonzero;stroke:none;stroke-width:0.35277775;fill-opacity:1" | |||||
d="m 104.56144,65.803091 h -3.85851 v 9.1047 h 3.85851 z m 0,0" | |||||
id="path243334" | |||||
inkscape:connector-curvature="0" /> | |||||
</g> | |||||
<g | |||||
id="g258240" | |||||
transform="translate(0,-6.10471)"> | |||||
<path | |||||
style="fill:#424242;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.70156,71.907801 h 3.85988 v 2.99999 h -3.85988 z m 0,0" | |||||
id="path243340" | |||||
inkscape:connector-curvature="0" /> | |||||
<path | |||||
style="fill:#979797;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.70156,73.241742 h 3.85988 v 0.330729 h -3.85988 z m 0,0" | |||||
id="path243342" | |||||
inkscape:connector-curvature="0" /> | |||||
<path | |||||
style="fill:#979797;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.70156,74.577062 h 3.85988 v 0.330729 h -3.85988 z m 0,0" | |||||
id="path243344" | |||||
inkscape:connector-curvature="0" /> | |||||
<path | |||||
style="fill:#979797;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.70156,73.91009 h 3.85988 v 0.330729 h -3.85988 z m 0,0" | |||||
id="path243346" | |||||
inkscape:connector-curvature="0" /> | |||||
<path | |||||
style="fill:#979797;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.70156,72.574773 h 3.85988 v 0.330729 h -3.85988 z m 0,0" | |||||
id="path243348" | |||||
inkscape:connector-curvature="0" /> | |||||
<path | |||||
style="fill:#979797;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||||
d="m 100.70156,71.907801 h 3.85988 v 0.329349 h -3.85988 z m 0,0" | |||||
id="path243350" | |||||
inkscape:connector-curvature="0" /> | |||||
</g> | |||||
</g> | |||||
</svg> |
@@ -10,7 +10,8 @@ std::string gApplicationVersion = | |||||
#else | #else | ||||
""; | ""; | ||||
#endif | #endif | ||||
std::string gApiHost = "http://api.vcvrack.com"; | |||||
std::string gApiHost = "https://api.vcvrack.com"; | |||||
// std::string gApiHost = "http://localhost:8081"; | |||||
RackWidget *gRackWidget = NULL; | RackWidget *gRackWidget = NULL; | ||||
Toolbar *gToolbar = NULL; | Toolbar *gToolbar = NULL; | ||||
@@ -70,7 +70,7 @@ struct MetadataMenu : ListMenu { | |||||
// Plugin metadata | // Plugin metadata | ||||
if (!model->plugin->website.empty()) { | if (!model->plugin->website.empty()) { | ||||
addChild(construct<UrlItem>(&MenuEntry::text, "Website", &UrlItem::url, model->plugin->path)); | |||||
addChild(construct<UrlItem>(&MenuEntry::text, "Website", &UrlItem::url, model->plugin->website)); | |||||
} | } | ||||
if (!model->plugin->manual.empty()) { | if (!model->plugin->manual.empty()) { | ||||
addChild(construct<UrlItem>(&MenuEntry::text, "Manual", &UrlItem::url, model->plugin->manual)); | addChild(construct<UrlItem>(&MenuEntry::text, "Manual", &UrlItem::url, model->plugin->manual)); | ||||
@@ -120,10 +120,6 @@ struct ModelItem : MenuItem { | |||||
sModel = model; | sModel = model; | ||||
MenuItem::onMouseEnter(e); | MenuItem::onMouseEnter(e); | ||||
} | } | ||||
void onMouseLeave(EventMouseLeave &e) override { | |||||
sModel = NULL; | |||||
MenuItem::onMouseLeave(e); | |||||
} | |||||
}; | }; | ||||
@@ -1,11 +1,57 @@ | |||||
#include <thread> | #include <thread> | ||||
#include "app.hpp" | #include "app.hpp" | ||||
#include "plugin.hpp" | #include "plugin.hpp" | ||||
#include "gui.hpp" | |||||
#include "../ext/osdialog/osdialog.h" | |||||
namespace rack { | namespace rack { | ||||
struct SyncButton : Button { | |||||
bool checked = false; | |||||
bool available = false; | |||||
bool completed = false; | |||||
void step() override { | |||||
if (!checked) { | |||||
std::thread t([this]() { | |||||
if (pluginSync(true)) | |||||
available = true; | |||||
}); | |||||
t.detach(); | |||||
checked = true; | |||||
} | |||||
if (completed) { | |||||
if (osdialog_message(OSDIALOG_INFO, OSDIALOG_OK_CANCEL, "All plugins have been updated. Close Rack and re-launch it to load new updates.")) { | |||||
guiClose(); | |||||
} | |||||
completed = false; | |||||
} | |||||
} | |||||
void draw(NVGcontext *vg) override { | |||||
Button::draw(vg); | |||||
if (available) { | |||||
// Notification circle | |||||
nvgBeginPath(vg); | |||||
nvgCircle(vg, 3, 3, 4.0); | |||||
nvgFillColor(vg, nvgRGBf(1.0, 0.0, 0.0)); | |||||
nvgFill(vg); | |||||
nvgStrokeColor(vg, nvgRGBf(0.5, 0.0, 0.0)); | |||||
nvgStroke(vg); | |||||
} | |||||
} | |||||
void onAction(EventAction &e) override { | |||||
available = false; | |||||
std::thread t([this]() { | |||||
if (pluginSync(false)) | |||||
completed = true; | |||||
}); | |||||
t.detach(); | |||||
} | |||||
}; | |||||
PluginManagerWidget::PluginManagerWidget() { | PluginManagerWidget::PluginManagerWidget() { | ||||
box.size.y = BND_WIDGET_HEIGHT; | box.size.y = BND_WIDGET_HEIGHT; | ||||
float margin = 5; | float margin = 5; | ||||
@@ -91,19 +137,13 @@ PluginManagerWidget::PluginManagerWidget() { | |||||
manageWidget->addChild(manageButton); | manageWidget->addChild(manageButton); | ||||
pos.x += manageButton->box.size.x; | pos.x += manageButton->box.size.x; | ||||
struct RefreshButton : Button { | |||||
void onAction(EventAction &e) override { | |||||
std::thread t(pluginRefresh); | |||||
t.detach(); | |||||
} | |||||
}; | |||||
pos.x += margin; | pos.x += margin; | ||||
Button *refreshButton = new RefreshButton(); | |||||
refreshButton->box.pos = pos; | |||||
refreshButton->box.size.x = 125; | |||||
refreshButton->text = "Refresh plugins"; | |||||
manageWidget->addChild(refreshButton); | |||||
pos.x += refreshButton->box.size.x; | |||||
Button *syncButton = new SyncButton(); | |||||
syncButton->box.pos = pos; | |||||
syncButton->box.size.x = 125; | |||||
syncButton->text = "Update plugins"; | |||||
manageWidget->addChild(syncButton); | |||||
pos.x += syncButton->box.size.x; | |||||
struct LogOutButton : Button { | struct LogOutButton : Button { | ||||
void onAction(EventAction &e) override { | void onAction(EventAction &e) override { | ||||
@@ -7,11 +7,12 @@ | |||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
#include <sys/param.h> // for MAXPATHLEN | #include <sys/param.h> // for MAXPATHLEN | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <thread> | |||||
#include <zip.h> | #include <zip.h> | ||||
#include <jansson.h> | #include <jansson.h> | ||||
#if ARCH_WIN | |||||
#if defined(ARCH_WIN) | |||||
#include <windows.h> | #include <windows.h> | ||||
#include <direct.h> | #include <direct.h> | ||||
#define mkdir(_dir, _perms) _mkdir(_dir) | #define mkdir(_dir, _perms) _mkdir(_dir) | ||||
@@ -189,35 +190,55 @@ static int extractZip(const char *filename, const char *dir) { | |||||
return err; | return err; | ||||
} | } | ||||
static void refreshPurchase(json_t *pluginJ) { | |||||
static void syncPlugin(json_t *pluginJ) { | |||||
json_t *slugJ = json_object_get(pluginJ, "slug"); | json_t *slugJ = json_object_get(pluginJ, "slug"); | ||||
if (!slugJ) return; | if (!slugJ) return; | ||||
std::string slug = json_string_value(slugJ); | std::string slug = json_string_value(slugJ); | ||||
info("Syncing plugin %s", slug.c_str()); | |||||
json_t *nameJ = json_object_get(pluginJ, "name"); | json_t *nameJ = json_object_get(pluginJ, "name"); | ||||
if (!nameJ) return; | if (!nameJ) return; | ||||
std::string name = json_string_value(nameJ); | std::string name = json_string_value(nameJ); | ||||
json_t *versionJ = json_object_get(pluginJ, "version"); | |||||
if (!versionJ) return; | |||||
std::string version = json_string_value(versionJ); | |||||
// Check whether the plugin is already loaded | |||||
for (Plugin *plugin : gPlugins) { | |||||
if (plugin->slug == slug && plugin->version == version) { | |||||
return; | |||||
std::string download; | |||||
std::string sha256; | |||||
json_t *downloadsJ = json_object_get(pluginJ, "downloads"); | |||||
if (downloadsJ) { | |||||
#if defined(ARCH_WIN) | |||||
#define DOWNLOADS_ARCH "win" | |||||
#elif defined(ARCH_MAC) | |||||
#define DOWNLOADS_ARCH "mac" | |||||
#elif defined(ARCH_LIN) | |||||
#define DOWNLOADS_ARCH "lin" | |||||
#endif | |||||
json_t *archJ = json_object_get(downloadsJ, DOWNLOADS_ARCH); | |||||
if (archJ) { | |||||
// Get download URL | |||||
json_t *downloadJ = json_object_get(archJ, "download"); | |||||
if (downloadJ) | |||||
download = json_string_value(downloadJ); | |||||
// Get SHA256 hash | |||||
json_t *sha256J = json_object_get(archJ, "sha256"); | |||||
if (sha256J) | |||||
sha256 = json_string_value(sha256J); | |||||
} | } | ||||
} | } | ||||
// Append token and version to download URL | |||||
std::string url = gApiHost; | |||||
url += "/download"; | |||||
url += "?product="; | |||||
url += slug; | |||||
url += "&version="; | |||||
url += requestEscape(gApplicationVersion); | |||||
url += "&token="; | |||||
url += requestEscape(gToken); | |||||
json_t *productIdJ = json_object_get(pluginJ, "productId"); | |||||
if (productIdJ) { | |||||
download = gApiHost; | |||||
download += "/download"; | |||||
download += "?slug="; | |||||
download += slug; | |||||
download += "&token="; | |||||
download += requestEscape(gToken); | |||||
} | |||||
if (download.empty()) { | |||||
warn("Could not get download URL for plugin %s", slug.c_str()); | |||||
return; | |||||
} | |||||
// If plugin is not loaded, download the zip file to /plugins | // If plugin is not loaded, download the zip file to /plugins | ||||
downloadName = name; | downloadName = name; | ||||
@@ -227,21 +248,127 @@ static void refreshPurchase(json_t *pluginJ) { | |||||
std::string pluginsDir = assetLocal("plugins"); | std::string pluginsDir = assetLocal("plugins"); | ||||
std::string pluginPath = pluginsDir + "/" + slug; | std::string pluginPath = pluginsDir + "/" + slug; | ||||
std::string zipPath = pluginPath + ".zip"; | std::string zipPath = pluginPath + ".zip"; | ||||
bool success = requestDownload(url, zipPath, &downloadProgress); | |||||
bool success = requestDownload(download, zipPath, &downloadProgress); | |||||
if (success) { | if (success) { | ||||
if (!sha256.empty()) { | |||||
// Check SHA256 hash | |||||
std::string actualSha256 = requestSHA256File(zipPath); | |||||
if (actualSha256 != sha256) { | |||||
warn("Plugin %s does not match expected SHA256 checksum", slug.c_str()); | |||||
return; | |||||
} | |||||
} | |||||
// Unzip file | // Unzip file | ||||
int err = extractZip(zipPath.c_str(), pluginsDir.c_str()); | int err = extractZip(zipPath.c_str(), pluginsDir.c_str()); | ||||
if (!err) { | if (!err) { | ||||
// Delete zip | // Delete zip | ||||
remove(zipPath.c_str()); | remove(zipPath.c_str()); | ||||
// Load plugin | // Load plugin | ||||
loadPlugin(pluginPath); | |||||
// loadPlugin(pluginPath); | |||||
} | } | ||||
} | } | ||||
downloadName = ""; | downloadName = ""; | ||||
} | } | ||||
static bool trySyncPlugin(json_t *pluginJ, json_t *communityPluginsJ, bool dryRun) { | |||||
std::string slug = json_string_value(pluginJ); | |||||
// Find community plugin | |||||
size_t communityIndex; | |||||
json_t *communityPluginJ = NULL; | |||||
json_array_foreach(communityPluginsJ, communityIndex, communityPluginJ) { | |||||
json_t *communitySlugJ = json_object_get(communityPluginJ, "slug"); | |||||
if (communitySlugJ) { | |||||
std::string communitySlug = json_string_value(communitySlugJ); | |||||
if (slug == communitySlug) | |||||
break; | |||||
} | |||||
} | |||||
if (communityIndex == json_array_size(communityPluginsJ)) { | |||||
warn("Plugin sync error: %s not found in community", slug.c_str()); | |||||
return false; | |||||
} | |||||
// Get community version | |||||
std::string version; | |||||
json_t *versionJ = json_object_get(communityPluginJ, "version"); | |||||
if (versionJ) { | |||||
version = json_string_value(versionJ); | |||||
} | |||||
// Check whether we already have a plugin with the same slug and version | |||||
for (Plugin *plugin : gPlugins) { | |||||
if (plugin->slug == slug) { | |||||
// plugin->version might be blank, so adding a version of the manifest will update the plugin | |||||
if (plugin->version == version) | |||||
return false; | |||||
} | |||||
} | |||||
if (!dryRun) | |||||
syncPlugin(communityPluginJ); | |||||
return true; | |||||
} | |||||
bool pluginSync(bool dryRun) { | |||||
if (gToken.empty()) | |||||
return false; | |||||
bool available = false; | |||||
// Download my plugins | |||||
json_t *reqJ = json_object(); | |||||
json_object_set(reqJ, "version", json_string(gApplicationVersion.c_str())); | |||||
json_object_set(reqJ, "token", json_string(gToken.c_str())); | |||||
json_t *resJ = requestJson(METHOD_GET, gApiHost + "/plugins", reqJ); | |||||
json_decref(reqJ); | |||||
// Download community plugins | |||||
json_t *communityResJ = requestJson(METHOD_GET, gApiHost + "/community/plugins", NULL); | |||||
if (!dryRun) { | |||||
isDownloading = true; | |||||
downloadProgress = 0.0; | |||||
downloadName = ""; | |||||
} | |||||
if (resJ && communityResJ) { | |||||
json_t *errorJ = json_object_get(resJ, "error"); | |||||
json_t *communityErrorJ = json_object_get(resJ, "error"); | |||||
if (errorJ) { | |||||
warn("Plugin sync error: %s", json_string_value(errorJ)); | |||||
} | |||||
else if (communityErrorJ) { | |||||
warn("Plugin sync error: %s", json_string_value(communityErrorJ)); | |||||
} | |||||
else { | |||||
// Check each plugin in list of my plugins | |||||
json_t *pluginsJ = json_object_get(resJ, "plugins"); | |||||
json_t *communityPluginsJ = json_object_get(communityResJ, "plugins"); | |||||
size_t index; | |||||
json_t *pluginJ; | |||||
json_array_foreach(pluginsJ, index, pluginJ) { | |||||
if (trySyncPlugin(pluginJ, communityPluginsJ, dryRun)) | |||||
available = true; | |||||
} | |||||
} | |||||
} | |||||
if (resJ) | |||||
json_decref(resJ); | |||||
if (communityResJ) | |||||
json_decref(communityResJ); | |||||
if (!dryRun) { | |||||
isDownloading = false; | |||||
} | |||||
return available; | |||||
} | |||||
//////////////////// | //////////////////// | ||||
// plugin API | // plugin API | ||||
//////////////////// | //////////////////// | ||||
@@ -271,10 +398,10 @@ void pluginInit() { | |||||
void pluginDestroy() { | void pluginDestroy() { | ||||
for (Plugin *plugin : gPlugins) { | for (Plugin *plugin : gPlugins) { | ||||
// Free library handle | // Free library handle | ||||
#if ARCH_WIN | |||||
#if defined(ARCH_WIN) | |||||
if (plugin->handle) | if (plugin->handle) | ||||
FreeLibrary((HINSTANCE)plugin->handle); | FreeLibrary((HINSTANCE)plugin->handle); | ||||
#elif ARCH_LIN || ARCH_MAC | |||||
#elif defined(ARCH_LIN) || defined(ARCH_MAC) | |||||
if (plugin->handle) | if (plugin->handle) | ||||
dlclose(plugin->handle); | dlclose(plugin->handle); | ||||
#endif | #endif | ||||
@@ -315,39 +442,6 @@ void pluginLogOut() { | |||||
gToken = ""; | gToken = ""; | ||||
} | } | ||||
void pluginRefresh() { | |||||
if (gToken.empty()) | |||||
return; | |||||
isDownloading = true; | |||||
downloadProgress = 0.0; | |||||
downloadName = ""; | |||||
json_t *reqJ = json_object(); | |||||
json_object_set(reqJ, "token", json_string(gToken.c_str())); | |||||
json_t *resJ = requestJson(METHOD_GET, gApiHost + "/purchases", reqJ); | |||||
json_decref(reqJ); | |||||
if (resJ) { | |||||
json_t *errorJ = json_object_get(resJ, "error"); | |||||
if (errorJ) { | |||||
const char *errorStr = json_string_value(errorJ); | |||||
warn("Plugin refresh error: %s", errorStr); | |||||
} | |||||
else { | |||||
json_t *purchasesJ = json_object_get(resJ, "purchases"); | |||||
size_t index; | |||||
json_t *purchaseJ; | |||||
json_array_foreach(purchasesJ, index, purchaseJ) { | |||||
refreshPurchase(purchaseJ); | |||||
} | |||||
} | |||||
json_decref(resJ); | |||||
} | |||||
isDownloading = false; | |||||
} | |||||
void pluginCancelDownload() { | void pluginCancelDownload() { | ||||
// TODO | // TODO | ||||
} | } | ||||
@@ -4,6 +4,7 @@ | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <curl/curl.h> | #include <curl/curl.h> | ||||
#include <openssl/sha.h> | |||||
namespace rack { | namespace rack { | ||||
@@ -79,6 +80,7 @@ json_t *requestJson(RequestMethod method, std::string url, json_t *dataJ) { | |||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, reqStr); | curl_easy_setopt(curl, CURLOPT_POSTFIELDS, reqStr); | ||||
std::string resText; | std::string resText; | ||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); | |||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeStringCallback); | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeStringCallback); | ||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resText); | curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resText); | ||||
@@ -130,6 +132,8 @@ bool requestDownload(std::string url, std::string filename, float *progress) { | |||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, file); | curl_easy_setopt(curl, CURLOPT_WRITEDATA, file); | ||||
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferInfoCallback); | curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferInfoCallback); | ||||
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, progress); | curl_easy_setopt(curl, CURLOPT_XFERINFODATA, progress); | ||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true); | |||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); | |||||
info("Downloading %s", url.c_str()); | info("Downloading %s", url.c_str()); | ||||
CURLcode res = curl_easy_perform(curl); | CURLcode res = curl_easy_perform(curl); | ||||
@@ -153,5 +157,36 @@ std::string requestEscape(std::string s) { | |||||
return ret; | return ret; | ||||
} | } | ||||
std::string requestSHA256File(std::string filename) { | |||||
FILE *f = fopen(filename.c_str(), "rb"); | |||||
if (!f) | |||||
return ""; | |||||
uint8_t hash[SHA256_DIGEST_LENGTH]; | |||||
SHA256_CTX sha256; | |||||
SHA256_Init(&sha256); | |||||
const int bufferLen = 1 << 15; | |||||
uint8_t *buffer = new uint8_t[bufferLen]; | |||||
int len = 0; | |||||
while ((len = fread(buffer, 1, bufferLen, f))) { | |||||
SHA256_Update(&sha256, buffer, len); | |||||
} | |||||
SHA256_Final(hash, &sha256); | |||||
delete[] buffer; | |||||
fclose(f); | |||||
// Convert binary hash to hex | |||||
char hashHex[64]; | |||||
const char hexTable[] = "0123456789abcdef"; | |||||
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { | |||||
uint8_t h = hash[i]; | |||||
hashHex[2*i + 0] = hexTable[h >> 4]; | |||||
hashHex[2*i + 1] = hexTable[h & 0x0f]; | |||||
} | |||||
std::string str(hashHex, sizeof(hashHex)); | |||||
return str; | |||||
} | |||||
} // namespace rack | } // namespace rack |