diff --git a/react/public/var/config.json b/react/public/var/config.json index 5711fff..ff7662c 100644 --- a/react/public/var/config.json +++ b/react/public/var/config.json @@ -5,5 +5,6 @@ "max_upload_size": 536870912, "fakeAndroid": false, "ui_plugins": [], - "enable_auto_update": true + "enable_auto_update": true, + "has_wifi_device": false } \ No newline at end of file diff --git a/react/src/PiPedalModel.tsx b/react/src/PiPedalModel.tsx index 5b188c8..cb37bb8 100644 --- a/react/src/PiPedalModel.tsx +++ b/react/src/PiPedalModel.tsx @@ -394,7 +394,7 @@ export class PiPedalModel //implements PiPedalModel webSocket?: PiPedalSocket; - + hasWifiDevice: ObservableProperty = new ObservableProperty(false); onSnapshotModified: ObservableEvent = new ObservableEvent(); ui_plugins: ObservableProperty @@ -1036,6 +1036,7 @@ export class PiPedalModel //implements PiPedalModel ) .then(data => { this.enableAutoUpdate = !!data.enable_auto_update; + this.hasWifiDevice.set(!!data.has_wifi_device); if (data.max_upload_size) { this.maxPresetUploadSize = data.max_upload_size; } diff --git a/react/src/SettingsDialog.tsx b/react/src/SettingsDialog.tsx index 0009618..fce513f 100644 --- a/react/src/SettingsDialog.tsx +++ b/react/src/SettingsDialog.tsx @@ -92,6 +92,8 @@ interface SettingsDialogState { showRestartOkDialog: boolean; showShutdownOkDialog: boolean; showSystemMidiBindingsDialog: boolean; + + hasWifiDevice: boolean; }; @@ -199,10 +201,8 @@ const SettingsDialog = withStyles(styles, { withTheme: true })( showShutdownOkDialog: false, showRestartOkDialog: false, showSystemMidiBindingsDialog: false, - isAndroidHosted: this.model.isAndroidHosted() - - - + isAndroidHosted: this.model.isAndroidHosted(), + hasWifiDevice: this.model.hasWifiDevice.get() }; this.handleJackConfigurationChanged = this.handleJackConfigurationChanged.bind(this); this.handleJackSettingsChanged = this.handleJackSettingsChanged.bind(this); @@ -213,7 +213,6 @@ const SettingsDialog = withStyles(styles, { withTheme: true })( this.handleConnectionStateChanged = this.handleConnectionStateChanged.bind(this); this.handleShowStatusMonitorChanged = this.handleShowStatusMonitorChanged.bind(this); - } @@ -542,7 +541,7 @@ const SettingsDialog = withStyles(styles, { withTheme: true })( { this.props.onClose() }} TransitionComponent={Transition} style={{ userSelect: "none" }} - onEnterKey={()=>{}} + onEnterKey={() => { }} >
@@ -651,7 +650,7 @@ const SettingsDialog = withStyles(styles, { withTheme: true })( - this.handleInputSelection()} + this.handleInputSelection()} disabled={!isConfigValid || this.state.jackConfiguration.outputAudioPorts.length <= 1} style={{ opacity: !isConfigValid ? 0.6 : 1.0 }} @@ -662,7 +661,7 @@ const SettingsDialog = withStyles(styles, { withTheme: true })( {this.state.jackSettings.getAudioInputDisplayValue(this.state.jackConfiguration)}
- this.handleOutputSelection()} + this.handleOutputSelection()} disabled={!isConfigValid || this.state.jackConfiguration.outputAudioPorts.length <= 1} style={{ opacity: !isConfigValid ? 0.6 : 1.0 }} > @@ -766,43 +765,52 @@ const SettingsDialog = withStyles(styles, { withTheme: true })( ) } - -
- CONNECTION + {(this.state.hasWifiDevice || this.state.isAndroidHosted) && + ( +
+ +
+ CONNECTION - this.handleShowWifiConfigDialog()} > - -
- - Wi-Fi auto-hotspot - - {this.state.wifiConfigSettings.getSummaryText()} - + {this.state.hasWifiDevice && ( + this.handleShowWifiConfigDialog()} > + +
+ + Wi-Fi auto-hotspot + + {this.state.wifiConfigSettings.getSummaryText()} + + +
+
+ + )} + + { + this.state.isAndroidHosted && + ( + this.model.chooseNewDevice()} > + +
+ + Connect to a different device + + + + +
+
+ ) + } + +
- - - { - this.state.isAndroidHosted && - ( - this.model.chooseNewDevice()} > - -
- - Connect to a different device - - - - -
-
- ) - } - -
+ )} {(!this.props.onboarding) ? (
@@ -942,10 +950,15 @@ const SettingsDialog = withStyles(styles, { withTheme: true })( ) } - this.setState({ showWifiDirectConfigDialog: false })} - onOk={(wifiDirectConfigSettings: WifiDirectConfigSettings) => this.handleApplyWifiDirectConfig(wifiDirectConfigSettings)} - /> + { + this.state.showWifiDirectConfigDialog && ( + this.setState({ showWifiDirectConfigDialog: false })} + onOk={(wifiDirectConfigSettings: WifiDirectConfigSettings) => this.handleApplyWifiDirectConfig(wifiDirectConfigSettings)} + /> + + ) + } { this.setState({ showRestartOkDialog: false }); this.handleRestartOk(); }} @@ -956,10 +969,13 @@ const SettingsDialog = withStyles(styles, { withTheme: true })( onOk={() => { this.setState({ showShutdownOkDialog: false }); this.handleShutdownOk(); }} onClose={() => { this.setState({ showShutdownOkDialog: false }); }} /> - { this.setState({ showSystemMidiBindingsDialog: false }); }} - /> + {this.state.showSystemMidiBindingsDialog && ( + { this.setState({ showSystemMidiBindingsDialog: false }); }} + /> + + )} {this.state.showWindowScaleDialog && ( this.setState({ showWindowScaleDialog: false }))} diff --git a/src/HotspotManager.cpp b/src/HotspotManager.cpp index 8d9de21..9bb8134 100644 --- a/src/HotspotManager.cpp +++ b/src/HotspotManager.cpp @@ -33,6 +33,7 @@ using namespace pipedal; using namespace dbus::networkmanager; +namespace fs = std::filesystem; namespace pipedal::impl { @@ -1032,3 +1033,33 @@ std::vector HotspotManagerImpl::GetKnownWifiNetworks() std::lock_guard lock(knownWifiNetworksMutex); // pushed off the service thread. return this->knownWifiNetworks; } + + +static bool is_wireless_sysfs(const std::string& ifname) { + return fs::exists("/sys/class/net/" + ifname + "/wireless"); +} + +static std::vector get_wireless_interfaces_sysfs() { + std::vector wireless_interfaces; + const std::string net_path = "/sys/class/net"; + + try { + for (const auto& entry : fs::directory_iterator(net_path)) { + std::string ifname = entry.path().filename(); + if (is_wireless_sysfs(ifname)) { + wireless_interfaces.push_back(ifname); + } + } + } catch (const fs::filesystem_error& e) { + std::cerr << "Error accessing " << net_path << ": " << e.what() << std::endl; + } + + return wireless_interfaces; +} + +bool HotspotManager::HasWifiDevice() +{ + // use procfs to decide this, as NetworkManager may not be available yet. + + return !(get_wireless_interfaces_sysfs().empty()); +} diff --git a/src/HotspotManager.hpp b/src/HotspotManager.hpp index cd4958e..1e66f01 100644 --- a/src/HotspotManager.hpp +++ b/src/HotspotManager.hpp @@ -38,6 +38,8 @@ namespace pipedal { using ptr = std::unique_ptr; + static bool HasWifiDevice(); + static ptr Create(); virtual ~HotspotManager() noexcept { } diff --git a/src/WebServerConfig.cpp b/src/WebServerConfig.cpp index 4097268..59c8337 100644 --- a/src/WebServerConfig.cpp +++ b/src/WebServerConfig.cpp @@ -33,6 +33,7 @@ #include "TemporaryFile.hpp" #include "PresetBundle.hpp" #include "json.hpp" +#include "HotspotManager.hpp" #define OLD_PRESET_EXTENSION ".piPreset" #define PRESET_EXTENSION ".piPreset" @@ -701,6 +702,7 @@ public: << ", \"socket_server_address\": \"" << webSocketAddress << "\", \"ui_plugins\": [ ], \"max_upload_size\": " << maxUploadSize << ", \"enable_auto_update\": " << (ENABLE_AUTO_UPDATE ? " true" : "false") + << ", \"has_wifi_device\": " << (HotspotManager::HasWifiDevice() ? " true": "false") << " }"; return s.str(); diff --git a/todo.txt b/todo.txt index ffdaf18..3d52fb7 100644 --- a/todo.txt +++ b/todo.txt @@ -1,28 +1,7 @@ -Loading shields need to be of Modal type. - -MOD fileTypes - - - audioloop: Audio Loops, meant to be used for looper-style plugins - - audiorecording: Audio Recordings, triggered by plugins and stored in the unit - - audiosample: One-shot Audio Samples, meant to be used for sampler-style plugins - - audiotrack: Audio Tracks, meant to be used as full-performance/song or backtrack - - cabsim: Speaker Cabinets, meant as small IR audio files - - h2drumkit: Hydrogen Drumkits, must use h2drumkit file extension - - ir: Impulse Responses - - midiclip: MIDI Clips, to be used in sync with host tempo, must have mid or midi file extension - - midisong: MIDI Songs, meant to be used as full-performance/song or backtrack - - sf2: SF2 Instruments, must have sf2 or sf3 file extension - - sfz: SFZ Instruments, must have sfz file extension +Not all country codes are valid (e.g. Antarctica) -Main menu on Pixel 5 client. -x1 bank menu (landscape pixel 5) should show current bank. - -Restart discover on network change? - - --verify clean removal of dhcpcd and nm_p2p2d X Review docs changes once we go live.