diff --git a/.travis.yml b/.travis.yml index c81e354aa..b25d3eea6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ jobs: branches: only: - master + - development before_install: - if [ "$TRAVIS_OS_NAME" = osx ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then openssl aes-256-cbc -K $encrypted_2f5d2771e3cb_key -iv $encrypted_2f5d2771e3cb_iv -in release_script/mac_only/Certificates.p12.enc -out release_script/mac_only/Certificates.p12 -d; fi @@ -68,4 +69,4 @@ after_success: notifications: email: on_success: never - on_failure: always \ No newline at end of file + on_failure: always diff --git a/CHANGELOG.md b/CHANGELOG.md index 468107c26..4336d8ffd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# v5.0.7 + +### Improvements +* Show info in footer when a new version of the GUI is available #992 +* Further improvements to GUI Update Button logic +* Add GUI-wide settings class to keep certain settings across sessions and app starts #997 +* Remove 30 second window option from Focus widget + +### Bug Fixes +* Fix GUI not running on some Macs due to high-dpi screen code #987 #990 #1001 +* Fix streaming multiple data types over LSL #971 + # v5.0.6 ### Improvements diff --git a/Networking-Test-Kit/LSL/lslStreamTest.py b/Networking-Test-Kit/LSL/lslStreamTest.py index 6fce85048..d7cb303b5 100644 --- a/Networking-Test-Kit/LSL/lslStreamTest.py +++ b/Networking-Test-Kit/LSL/lslStreamTest.py @@ -9,7 +9,7 @@ # create a new inlet to read from the stream inlet = StreamInlet(streams[0]) -duration = 2 +duration = 5 sleep(1) @@ -18,17 +18,18 @@ def testLSLSamplingRate(): totalNumSamples = 0 validSamples = 0 numChunks = 0 + print( "Testing Sampling Rates..." ) while time.time() <= start + duration: # get chunks of samples - samples, timestamp = inlet.pull_chunk() - if samples: + chunk, timestamp = inlet.pull_chunk() + if chunk: numChunks += 1 - print( len(samples) ) - totalNumSamples += len(samples) - # print(samples); - for sample in samples: - print(sample) + # print( len(chunk) ) + totalNumSamples += len(chunk) + # print(chunk); + for sample in chunk: + # print(sample) validSamples += 1 print( "Number of Chunks and Samples == {} , {}".format(numChunks, totalNumSamples) ) diff --git a/Networking-Test-Kit/LSL/lslStreamTest_3Streams.py b/Networking-Test-Kit/LSL/lslStreamTest_3Streams.py index bca94ade1..73d7ed21b 100644 --- a/Networking-Test-Kit/LSL/lslStreamTest_3Streams.py +++ b/Networking-Test-Kit/LSL/lslStreamTest_3Streams.py @@ -10,43 +10,51 @@ import time numStreams = 3 +duration_seconds = 20 # first resolve an EEG stream on the lab network print("looking for an EEG stream...") -stream1 = resolve_stream('type', 'EEG') -stream2 = resolve_stream('type', 'AUX') -stream3 = resolve_stream('type', 'FFT') +stream_1 = resolve_stream('type', 'EEG') +stream_2 = resolve_stream('type', 'AUX') +stream_3 = resolve_stream('type', 'FOCUS') # create a new inlet to read from the stream -inlet = StreamInlet(stream1[0]) -inlet2 = StreamInlet(stream2[0]) -inlet3 = StreamInlet(stream3[0]) +inlet = StreamInlet(stream_1[0]) +intlet_2 = StreamInlet(stream_2[0]) +intlet_3 = StreamInlet(stream_3[0]) def testLSLSamplingRates(): - print( "Testing Sampling Rates..." ) + print( "Testing Sampling Rates for {} seconds".format(duration_seconds) ) start = time.time() - numSamples1 = 0 - numSamples2 = 0 - numSamples3 = 0 - while time.time() < start + 5: + num_samples_1 = 0 + num_samples_2 = 0 + num_samples_3 = 0 + while time.time() < start + duration_seconds: # get a new sample (you can also omit the timestamp part if you're not # interested in it) for i in range(numStreams): if i == 0: chunk, timestamps = inlet.pull_chunk() if timestamps: - numSamples1 += 1 + for sample in chunk: + if sample: + num_samples_1 += 1 + #print(sample) elif i == 1: - chunk, timestamps2 = inlet2.pull_chunk() - if timestamps2: - numSamples2 += 1 + chunk, timestamps_2 = intlet_2.pull_chunk() + if timestamps_2: + for sample in chunk: + num_samples_2 += 1 + #print(sample) elif i == 2: - chunk, timestamps3 = inlet3.pull_chunk() - if timestamps3: - numSamples3 += 1 + chunk, timestamps_3 = intlet_3.pull_chunk() + if timestamps_3: + for sample in chunk: + num_samples_3 += 1 + #print(sample) #print("Stream", i + 1, " == ", chunk) - print( "Stream 1 Sampling Rate == ", numSamples1, " | Type : EEG") - print( "Stream 2 Sampling Rate == ", numSamples2, " | Type : AUX") - print( "Stream 3 Sampling Rate == ", numSamples3, " | Type : FFT") + print( "Stream 1 Sampling Rate == ", num_samples_1 / duration_seconds, " | Type : EEG") + print( "Stream 2 Sampling Rate == ", num_samples_2 / duration_seconds, " | Type : AUX") + print( "Stream 3 Sampling Rate == ", num_samples_3 / duration_seconds, " | Type : FOCUS") testLSLSamplingRates() \ No newline at end of file diff --git a/Networking-Test-Kit/LSL/lslStreamTest_FFTplot.py b/Networking-Test-Kit/LSL/lslStreamTest_FFTplot.py index f2a2a715f..6a072d35a 100644 --- a/Networking-Test-Kit/LSL/lslStreamTest_FFTplot.py +++ b/Networking-Test-Kit/LSL/lslStreamTest_FFTplot.py @@ -11,16 +11,17 @@ last_print = time.time() fps_counter = deque(maxlen=150) +duration = 5 # first resolve an EEG stream on the lab network print("looking for an EEG stream...") -streams = resolve_stream('type', 'EEG') +streams = resolve_stream('type', 'FFT') # create a new inlet to read from the stream inlet = StreamInlet(streams[0]) channel_data = {} -for i in range(5): # how many iterations. Eventually this would be a while True +for i in range(duration): # how many iterations. Eventually this would be a while True for i in range(16): # each of the 16 channels here sample, timestamp = inlet.pull_sample() diff --git a/OpenBCI_GUI/ADS1299SettingsController.pde b/OpenBCI_GUI/ADS1299SettingsController.pde index 687701c66..1e8edb284 100644 --- a/OpenBCI_GUI/ADS1299SettingsController.pde +++ b/OpenBCI_GUI/ADS1299SettingsController.pde @@ -138,7 +138,7 @@ class ADS1299SettingsController { } } - boolean showCustomCommandUI = settings.expertModeToggle; + boolean showCustomCommandUI = guiSettings.getExpertModeBoolean(); //Draw background behind command buttons pushStyle(); diff --git a/OpenBCI_GUI/ControlPanel.pde b/OpenBCI_GUI/ControlPanel.pde index 144fb7c85..d3c3bfc45 100644 --- a/OpenBCI_GUI/ControlPanel.pde +++ b/OpenBCI_GUI/ControlPanel.pde @@ -2778,7 +2778,6 @@ class InitBox { } } else { //if system is already active ... stop session and flip button state back - outputInfo("Learn how to use this application and more at openbci.github.io/Documentation/"); setInitSessionButtonText("START SESSION"); topNav.setLockTopLeftSubNavCp5Objects(false); //Unlock top left subnav buttons //creates new data file name so that you don't accidentally overwrite the old one diff --git a/OpenBCI_GUI/CustomCp5Classes.pde b/OpenBCI_GUI/CustomCp5Classes.pde index f8f6490a1..6159b5b1a 100644 --- a/OpenBCI_GUI/CustomCp5Classes.pde +++ b/OpenBCI_GUI/CustomCp5Classes.pde @@ -90,7 +90,8 @@ class ButtonHelpText{ } public void draw(){ - if (!isVisible || settings.expertModeToggle) { + //When using expert mode, disable help text over UI objects + if (!isVisible || guiSettings.getExpertModeBoolean()) { return; } diff --git a/OpenBCI_GUI/Debugging.pde b/OpenBCI_GUI/Debugging.pde index 2892c5cd6..9d1412bf0 100644 --- a/OpenBCI_GUI/Debugging.pde +++ b/OpenBCI_GUI/Debugging.pde @@ -54,7 +54,7 @@ class HelpWidget { int padding; //current text shown in help widget, based on most recent command - String currentOutput = "Learn how to use this application and more at openbci.github.io/Documentation/"; + String currentOutput = "Learn how to use this application and more at docs.openbci.com"; OutputLevel curOutputLevel = OutputLevel.INFO; HelpWidget(float _xPos, float _yPos, float _width, float _height) { diff --git a/OpenBCI_GUI/FocusEnums.pde b/OpenBCI_GUI/FocusEnums.pde index e6bfe7dd7..accf680ed 100644 --- a/OpenBCI_GUI/FocusEnums.pde +++ b/OpenBCI_GUI/FocusEnums.pde @@ -14,8 +14,7 @@ public enum FocusXLim implements FocusEnum { FIVE (0, 5, "5 sec"), TEN (1, 10, "10 sec"), - TWENTY (2, 20, "20 sec"), - THIRTY (3, 30, "30 sec"); + TWENTY (2, 20, "20 sec"); private int index; private int value; diff --git a/OpenBCI_GUI/GuiSettings.pde b/OpenBCI_GUI/GuiSettings.pde new file mode 100644 index 000000000..8215c34d6 --- /dev/null +++ b/OpenBCI_GUI/GuiSettings.pde @@ -0,0 +1,116 @@ +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.io.*; + + +interface GuiSettingsEnum { + public String getName(); +} + +enum ExpertModeEnum implements GuiSettingsEnum { + ON("Active", true), + OFF("Inactive", false); + + private String name; + private boolean val; + + ExpertModeEnum(String _name, boolean _val) { + this.name = _name; + this.val = _val; + } + + @Override + public String getName() { + return name; + } + + public boolean getBooleanValue() { + return val; + } +} + +public class GuiSettingsValues { + private ExpertModeEnum expertMode = ExpertModeEnum.OFF; + + public GuiSettingsValues() { + } +} + +class GuiSettings { + + public GuiSettingsValues values; + private String filename; + + GuiSettings(String settingsDirectory) { + + values = new GuiSettingsValues(); + + StringBuilder settingsFilename = new StringBuilder(settingsDirectory); + settingsFilename.append("GuiWideSettings.json"); + filename = settingsFilename.toString(); + File fileToCheck = new File(filename); + boolean fileExists = fileToCheck.exists(); + if (fileExists) { + loadSettingsValues(); + println("OpenBCI_GUI::Settings: Found and loaded existing GUI-wide Settings from file."); + } else { + println("OpenBCI_GUI::Settings: Creating new GUI-wide Settings file."); + saveToFile(); + } + } + + public boolean loadSettingsValues() { + try { + File file = new File(filename); + StringBuilder fileContents = new StringBuilder((int)file.length()); + Scanner scanner = new Scanner(file); + while(scanner.hasNextLine()) { + fileContents.append(scanner.nextLine() + System.lineSeparator()); + } + Gson gson = new Gson(); + values = gson.fromJson(fileContents.toString(), GuiSettingsValues.class); + return true; + } catch (IOException e) { + e.printStackTrace(); + outputWarn("OpenBCI_GUI::Settings: Error loading GUI-wide settings from file. Attempting to create a new one."); + //If there is an error, attempt to overwrite the file or create a new one + saveToFile(); + return false; + } + } + + public String getJson() { + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + return gson.toJson(values); + } + + public boolean saveToFile() { + String json = getJson(); + try { + FileWriter writer = new FileWriter(filename); + writer.write(json); + writer.close(); + println("OpenBCI_GUI::Settings: Successfully saved GUI-wide settings to file!"); + return true; + } catch (IOException e) { + e.printStackTrace(); + outputWarn("OpenBCI_GUI::Settings: Error saving GUI-wide settings to file. Please make an issue on GitHub."); + return false; + } + } + + //Call this method at the end of GUI main Setup in OpenBCI_GUI.pde to make sure everything exists + //Has to be in this class to make sure other classes exist + public void applySettings() { + topNav.configSelector.toggleExpertModeFrontEnd(getExpertModeBoolean()); + } + + public void setExpertMode(ExpertModeEnum val) { + values.expertMode = val; + saveToFile(); + } + + public boolean getExpertModeBoolean() { + return values.expertMode.getBooleanValue(); + } +} \ No newline at end of file diff --git a/OpenBCI_GUI/Info.plist.tmpl b/OpenBCI_GUI/Info.plist.tmpl index 9aad9c08c..936cc6a2d 100644 --- a/OpenBCI_GUI/Info.plist.tmpl +++ b/OpenBCI_GUI/Info.plist.tmpl @@ -23,7 +23,7 @@ CFBundleShortVersionString 5 CFBundleVersion - 5.0.6 + 5.0.7 CFBundleSignature ???? NSHumanReadableCopyright @@ -32,7 +32,7 @@ Copyright © 2021 OpenBCI CFBundleGetInfoString - July 2021 + September 2021 @@jvm_runtime@@ diff --git a/OpenBCI_GUI/Interactivity.pde b/OpenBCI_GUI/Interactivity.pde index 6cfa6ceb4..614f8b378 100644 --- a/OpenBCI_GUI/Interactivity.pde +++ b/OpenBCI_GUI/Interactivity.pde @@ -31,7 +31,7 @@ synchronized void keyPressed() { boolean anyActiveTextfields = isNetworkingTextActive() || textFieldIsActive; if(!controlPanel.isOpen && !anyActiveTextfields){ //don't parse the key if the control panel is open - if (settings.expertModeToggle || key == ' ') { //Check if Expert Mode is On or Spacebar has been pressed + if (guiSettings.getExpertModeBoolean() || key == ' ') { //Check if Expert Mode is On or Spacebar has been pressed if ((int(key) >=32) && (int(key) <= 126)) { //32 through 126 represent all the usual printable ASCII characters parseKey(key); } diff --git a/OpenBCI_GUI/OpenBCI_GUI.pde b/OpenBCI_GUI/OpenBCI_GUI.pde index c7084707e..662590055 100644 --- a/OpenBCI_GUI/OpenBCI_GUI.pde +++ b/OpenBCI_GUI/OpenBCI_GUI.pde @@ -60,10 +60,11 @@ import http.requests.*; // Global Variables & Instances //------------------------------------------------------------------------ //Used to check GUI version in TopNav.pde and displayed on the splash screen on startup -String localGUIVersionString = "v5.0.6"; -String localGUIVersionDate = "July 2021"; +String localGUIVersionString = "v5.0.7"; +String localGUIVersionDate = "September 2021"; String guiLatestVersionGithubAPI = "https://api.github.com/repos/OpenBCI/OpenBCI_GUI/releases/latest"; String guiLatestReleaseLocation = "https://github.com/OpenBCI/OpenBCI_GUI/releases/latest"; +Boolean guiIsUpToDate; PApplet ourApplet; @@ -279,8 +280,9 @@ static CustomOutputStream outputStream; public final static String stopButton_pressToStop_txt = "Stop Data Stream"; public final static String stopButton_pressToStart_txt = "Start Data Stream"; -SessionSettings settings; DirectoryManager directoryManager; +SessionSettings settings; +GuiSettings guiSettings; final int navBarHeight = 32; TopNav topNav; @@ -288,6 +290,9 @@ TopNav topNav; ddf.minim.analysis.FFT[] fftBuff = new ddf.minim.analysis.FFT[nchan]; //from the minim library boolean isFFTFiltered = true; //yes by default ... this is used in dataProcessing.pde to determine which uV array feeds the FFT calculation +StringBuilder globalScreenResolution; +StringBuilder globalScreenDPI; + //------------------------------------------------------------------------ // Global Functions //------------------------------------------------------------------------ @@ -308,18 +313,18 @@ void settings() { win_h = 580; } size(win_w, win_h, P2D); -} -void setup() { - StringBuilder sb_res = new StringBuilder("Screen Resolution: "); - sb_res.append(displayWidth); - sb_res.append(" X "); - sb_res.append(displayHeight); + globalScreenResolution = new StringBuilder("Screen Resolution: "); + globalScreenResolution.append(displayWidth); + globalScreenResolution.append(" X "); + globalScreenResolution.append(displayHeight); //Account for high-dpi displays on Mac, Windows, and Linux Machines Fixes #968 pixelDensity(displayDensity()); - StringBuilder sb_dpi = new StringBuilder("High-DPI Screen Detected: "); - sb_dpi.append(displayDensity() == 2); + globalScreenDPI = new StringBuilder("High-DPI Screen Detected: "); + globalScreenDPI.append(displayDensity() == 2); +} +void setup() { frameRate(120); copyPaste = new CopyPaste(); @@ -381,15 +386,16 @@ void setup() { } println("Console Log Started at Local Time: " + directoryManager.getFileNameDateTime()); - println(sb_res.toString()); - println(sb_dpi.toString()); + println(globalScreenResolution.toString()); + println(globalScreenDPI.toString()); println(osName.toString()); println("Welcome to the Processing-based OpenBCI GUI!"); //Welcome line. - println("For more information, please visit: https://openbci.github.io/Documentation/docs/06Software/01-OpenBCISoftware/GUIDocs"); + println("For more information, please visit: https://docs.openbci.com/Software/OpenBCISoftware/GUIDocs/"); // Copy sample data to the Users' Documents folder + create Recordings folder directoryManager.init(); settings = new SessionSettings(); + guiSettings = new GuiSettings(directoryManager.getSettingsPath()); userPlaybackHistoryFile = directoryManager.getSettingsPath()+"UserPlaybackHistory.json"; //open window @@ -443,6 +449,9 @@ void delayedSetup() { setupComplete = true; // signal that the setup thread has finished println("OpenBCI_GUI::Setup: Setup is complete!"); } + + //Apply GUI-wide settings to front end at the end of setup + guiSettings.applySettings(); } //====================== END-OF-SETUP ==========================// @@ -644,8 +653,9 @@ void initSystem() { settings.init(); settings.initCheckPointFive(); } else if (eegDataSource == DATASOURCE_GALEA) { - //After TopNav has been instantiated, default to Expert mode for Galea - topNav.configSelector.toggleExpertMode(true); + //After TopNav has been instantiated, force Expert mode for Galea by default + topNav.configSelector.toggleExpertModeFrontEnd(true); + guiSettings.setExpertMode(ExpertModeEnum.ON); } //Make sure topNav buttons draw in the correct spot diff --git a/OpenBCI_GUI/SessionSettings.pde b/OpenBCI_GUI/SessionSettings.pde index a6fb91bfa..735e73d1a 100644 --- a/OpenBCI_GUI/SessionSettings.pde +++ b/OpenBCI_GUI/SessionSettings.pde @@ -25,9 +25,6 @@ // -- read the comments // -- once you find the right place to add your setting, you can copy the surrounding style // -- uses JSON keys -// -- Example: Expert Mode is a global boolean, so we include it under kJSONKeySettings -// -- We use one variable to load from JSON: loadExpertModeToggle -// -- And another variable to use in the GUI and with saving to JSON: expertModeToggle // -- Example2: GUI version and settings version // -- Requires new JSON key 'version` and settingsVersion // @@ -252,8 +249,6 @@ class SessionSettings { int loadFramerate; int loadDatasource; boolean dataSourceError = false; - //used globally to track and determine if expertMode is on or off - public boolean expertModeToggle = false; String saveDialogName; //Used when Save button is pressed String loadDialogName; //Used when Load button is pressed @@ -366,7 +361,6 @@ class SessionSettings { //Make a second JSON object within our JSONArray to store Global settings for the GUI JSONObject saveGlobalSettings = new JSONObject(); - saveGlobalSettings.setBoolean("Expert Mode", expertModeToggle); saveGlobalSettings.setInt("Current Layout", currentLayout); saveGlobalSettings.setInt("Notch", dataProcessing.bsRange.getIndex()); saveGlobalSettings.setInt("Bandpass Filter", dataProcessing.bpRange.getIndex()); @@ -587,7 +581,6 @@ class SessionSettings { //Load more global settings after this line, if needed int loadNotchSetting = loadGlobalSettings.getInt("Notch"); int loadBandpassSetting = loadGlobalSettings.getInt("Bandpass Filter"); - Boolean loadExpertModeToggle = loadGlobalSettings.getBoolean("Expert Mode"); Boolean loadDataSmoothingSetting = (currentBoard instanceof SmoothingCapableBoard) ? loadGlobalSettings.getBoolean("Data Smoothing") : null; //get the FFT settings @@ -763,10 +756,6 @@ class SessionSettings { topNav.updateSmoothingButtonText(); } - //Apply Expert Mode toggle - //This should not be loaded with other session settings - RW Jan 2021 - //topNav.configSelector.toggleExpertMode(loadExpertModeToggle); - //Load and apply all of the settings that are in dropdown menus. It's a bit much, so it has it's own function below. loadApplyWidgetDropdownText(); diff --git a/OpenBCI_GUI/TopNav.pde b/OpenBCI_GUI/TopNav.pde index 448dec2b9..0bf18568e 100644 --- a/OpenBCI_GUI/TopNav.pde +++ b/OpenBCI_GUI/TopNav.pde @@ -533,21 +533,35 @@ class TopNav { updateGuiVersionButton = createTNButton("updateGuiVersionButton", text, _x, _y, _w, _h, font, _fontSize, _bg, _textColor); //Attempt to compare local and remote GUI versions when TopNav is instantiated //This will also set the description/help-text for this cp5 button - final Boolean upToDate = guiVersionIsUpToDate(); + //Do this check on app start and store as a global variable + guiIsUpToDate = guiVersionIsUpToDate(); + updateGuiVersionButton.onRelease(new CallbackListener() { public void controlEvent(CallbackEvent theEvent) { - if (upToDate == null) { + //Perform check again when button is pressed. User may have connected to internet by now! + guiIsUpToDate = guiVersionIsUpToDate(); + + if (guiIsUpToDate == null) { + outputError("Update GUI: Unable to check for new version of GUI. Try again when connected to the internet."); return; } - if (!upToDate) { + if (!guiIsUpToDate) { openURLInBrowser(guiLatestReleaseLocation); - outputInfo("Update GUI: Opening latest Github release page using default browser"); + outputInfo("Update GUI: Opening latest GUI release page using default browser"); } else { outputSuccess("Update GUI: Local OpenBCI GUI is up-to-date!"); } } }); + + if (guiIsUpToDate == null) { + return; + } + + if (!guiIsUpToDate) { + outputWarn("Update Available! Press the \"Update\" button at the top of the GUI to download the latest version."); + } } private void createTopNavSettingsButton(String text, int _x, int _y, int _w, int _h, PFont font, int _fontSize, color _bg, color _textColor) { @@ -928,11 +942,13 @@ class ConfigSelector { expertMode.onRelease(new CallbackListener() { public void controlEvent(CallbackEvent theEvent) { toggleVisibility(); - toggleExpertMode(!settings.expertModeToggle); - String outputMsg = settings.expertModeToggle ? + boolean isActive = !guiSettings.getExpertModeBoolean(); + toggleExpertModeFrontEnd(isActive); + String outputMsg = isActive ? "Expert Mode ON: All keyboard shortcuts and features are enabled!" : "Expert Mode OFF: Use spacebar to start/stop the data stream."; output(outputMsg); + guiSettings.setExpertMode(isActive ? ExpertModeEnum.ON : ExpertModeEnum.OFF); } }); expertMode.setDescription("Expert Mode enables advanced keyboard shortcuts and access to all GUI features."); @@ -960,7 +976,7 @@ class ConfigSelector { loadSessionSettings.setDescription("Expert Mode enables advanced keyboard shortcuts and access to all GUI features."); } - private void createDefaultSettingsButton(String name, String text, int _x, int _y, int _w, int _h) { + private void createDefaultSettingsButton(String name, String text, int _x, int _y, int _w, int _h) { defaultSessionSettings = createButton(settings_cp5, name, text, _x, _y, _w, _h); defaultSessionSettings.onRelease(new CallbackListener() { public void controlEvent(CallbackEvent theEvent) { @@ -971,7 +987,7 @@ class ConfigSelector { defaultSessionSettings.setDescription("Expert Mode enables advanced keyboard shortcuts and access to all GUI features."); } - private void createClearAllSettingsButton(String name, String text, int _x, int _y, int _w, int _h) { + private void createClearAllSettingsButton(String name, String text, int _x, int _y, int _w, int _h) { clearAllGUISettings = createButton(settings_cp5, name, text, _x, _y, _w, _h, p5, 12, BUTTON_CAUTIONRED, WHITE); clearAllGUISettings.onRelease(new CallbackListener() { public void controlEvent(CallbackEvent theEvent) { @@ -985,7 +1001,7 @@ class ConfigSelector { clearAllGUISettings.setDescription("This will clear all user settings and playback history. You will be asked to confirm."); } - private void createClearSettingsNoButton(String name, String text, int _x, int _y, int _w, int _h) { + private void createClearSettingsNoButton(String name, String text, int _x, int _y, int _w, int _h) { clearAllSettingsNo = createButton(settings_cp5, name, text, _x, _y, _w, _h); clearAllSettingsNo.onRelease(new CallbackListener() { public void controlEvent(CallbackEvent theEvent) { @@ -998,7 +1014,7 @@ class ConfigSelector { }); } - private void createClearSettingsYesButton(String name, String text, int _x, int _y, int _w, int _h) { + private void createClearSettingsYesButton(String name, String text, int _x, int _y, int _w, int _h) { clearAllSettingsYes = createButton(settings_cp5, name, text, _x, _y, _w, _h); clearAllSettingsYes.onRelease(new CallbackListener() { public void controlEvent(CallbackEvent theEvent) { @@ -1017,17 +1033,13 @@ class ConfigSelector { clearAllSettingsYes.setDescription("Clicking 'Yes' will delete all user settings and stop the session if running."); } - public void toggleExpertMode(boolean b) { + public void toggleExpertModeFrontEnd(boolean b) { if (b) { expertMode.getCaptionLabel().setText("Turn Expert Mode Off"); expertMode.setColorBackground(BUTTON_EXPERTPURPLE); - println("GUI Settings: Expert Mode On"); - settings.expertModeToggle = true; } else { expertMode.getCaptionLabel().setText("Turn Expert Mode On"); expertMode.setColorBackground(BUTTON_NOOBGREEN); - println("GUI Settings: Expert Mode Off"); - settings.expertModeToggle = false; } } } @@ -1160,7 +1172,7 @@ class TutorialSelector { gettingStarted = createButton(tutorial_cp5, name, text, _x, _y, _w, _h); gettingStarted.onRelease(new CallbackListener() { public void controlEvent(CallbackEvent theEvent) { - openURLInBrowser("https://openbci.github.io/Documentation/docs/01GettingStarted/GettingStartedLanding"); + openURLInBrowser("https://docs.openbci.com/GettingStarted/GettingStartedLanding/"); toggleVisibility(); //shut layoutSelector if something is selected } }); @@ -1171,7 +1183,7 @@ class TutorialSelector { testingImpedance = createButton(tutorial_cp5, name, text, _x, _y, _w, _h); testingImpedance.onRelease(new CallbackListener() { public void controlEvent(CallbackEvent theEvent) { - openURLInBrowser("https://openbci.github.io/Documentation/docs/06Software/01-OpenBCISoftware/GUIDocs#impedance-testing"); + openURLInBrowser("https://docs.openbci.com/Software/OpenBCISoftware/GUIDocs/#impedance-testing"); toggleVisibility(); //shut layoutSelector if something is selected } }); @@ -1182,7 +1194,7 @@ class TutorialSelector { troubleshootingGuide = createButton(tutorial_cp5, name, text, _x, _y, _w, _h); troubleshootingGuide.onRelease(new CallbackListener() { public void controlEvent(CallbackEvent theEvent) { - openURLInBrowser("https://docs.openbci.com/docs/10Troubleshooting/GUI_Troubleshooting"); + openURLInBrowser("https://docs.openbci.com/Troubleshooting/GUI_Troubleshooting/"); toggleVisibility(); //shut layoutSelector if something is selected } }); @@ -1193,7 +1205,7 @@ class TutorialSelector { customWidgets = createButton(tutorial_cp5, name, text, _x, _y, _w, _h); customWidgets.onRelease(new CallbackListener() { public void controlEvent(CallbackEvent theEvent) { - openURLInBrowser("https://openbci.github.io/Documentation/docs/06Software/01-OpenBCISoftware/GUIWidgets#custom-widget"); + openURLInBrowser("https://docs.openbci.com/Software/OpenBCISoftware/GUIWidgets/#custom-widget"); toggleVisibility(); //shut layoutSelector if something is selected } }); diff --git a/OpenBCI_GUI/W_Networking.pde b/OpenBCI_GUI/W_Networking.pde index fdc55a46e..ad046c017 100644 --- a/OpenBCI_GUI/W_Networking.pde +++ b/OpenBCI_GUI/W_Networking.pde @@ -113,7 +113,7 @@ class W_Networking extends Widget { "obci_eeg1","EEG", "obci_eeg2","EEG", "obci_eeg3","EEG"}; - String networkingGuideURL = "https://openbci.github.io/Documentation/docs/06Software/01-OpenBCISoftware/GUIWidgets#networking"; + String networkingGuideURL = "https://docs.openbci.com/Software/OpenBCISoftware/GUIWidgets/#networking"; String dataOutputsURL = "https://docs.google.com/document/d/e/2PACX-1vR_4DXPTh1nuiOwWKwIZN3NkGP3kRwpP4Hu6fQmy3jRAOaydOuEI1jket6V4V6PG4yIG15H1N7oFfdV/pub"; boolean configIsVisible = false; boolean layoutIsVisible = false; @@ -121,7 +121,7 @@ class W_Networking extends Widget { private LinkedList dataAccumulationQueue; // accessed by individual streams. yes, i hate it too public float[][] dataBufferToSend; - public boolean newDataToSend = false; + public boolean newTimeSeriesDataToSend = false; HashMap cp5Map = new HashMap(); @@ -215,8 +215,6 @@ class W_Networking extends Widget { if (stream3!=null) { stream3.run(); } - //Setting this var here fixes #592 to allow multiple LSL streams - newDataToSend = false; } checkTopNovEvents(); @@ -287,7 +285,8 @@ class W_Networking extends Widget { } private void checkIfEnoughDataToSend() { - if (dataAccumulationQueue.size() >= nPointsPerUpdate) { + newTimeSeriesDataToSend = dataAccumulationQueue.size() >= nPointsPerUpdate; + if (newTimeSeriesDataToSend) { for (int iSample=0; iSample