Add local and remote ip address options to Accessories menu. Fixed a bug that allowed wine32 games to show up on the Raspberry Pi.
This commit is contained in:
@@ -5,6 +5,10 @@ Dates are given for the image. All items listed are available for the listed ima
|
|||||||
|
|
||||||
## September 1, 2025
|
## September 1, 2025
|
||||||
|
|
||||||
|
- Wine32 games only appear in x86_64
|
||||||
|
- Added local and remote ip address information to accessories menu
|
||||||
|
- Added Kitchensinc Games and Swamp to x86_64 image
|
||||||
|
- Set up wine32 on x86_64 image
|
||||||
- Fixed a bug with ocr, should work on both images now
|
- Fixed a bug with ocr, should work on both images now
|
||||||
- Hopefully fix a bug where setting default voice would sometimes not save across reboots.
|
- Hopefully fix a bug where setting default voice would sometimes not save across reboots.
|
||||||
- Add pitch and volume parameters to the rate script
|
- Add pitch and volume parameters to the rate script
|
||||||
@@ -14,6 +18,9 @@ Dates are given for the image. All items listed are available for the listed ima
|
|||||||
- Fix bug with resizing disk in x86_64
|
- Fix bug with resizing disk in x86_64
|
||||||
- Installed missing packages for text games. Remembered the games, forgot the dependencies
|
- Installed missing packages for text games. Remembered the games, forgot the dependencies
|
||||||
|
|
||||||
|
During this release cycle my development box broke in a very unusual way. The computer itself seems to work fine, but it will no longer boot from usb. I, thinking the image was broken, started over.
|
||||||
|
I am sure you know or have some idea of how much work was involved in that. Fortunately, I now have a working temporary development machine, so development can continue.
|
||||||
|
|
||||||
|
|
||||||
## August 1, 2025
|
## August 1, 2025
|
||||||
|
|
||||||
|
|||||||
@@ -916,8 +916,11 @@ if __name__ == "__main__":
|
|||||||
menu.add_item("Arcade", "Villains From Beyond", "GAME='Villains From Beyond' startx")
|
menu.add_item("Arcade", "Villains From Beyond", "GAME='Villains From Beyond' startx")
|
||||||
menu.add_item("Arcade", "Wicked Quest", "GAME='Wicked Quest' startx")
|
menu.add_item("Arcade", "Wicked Quest", "GAME='Wicked Quest' startx")
|
||||||
menu.add_item("Arcade", "Zombowl", "GAME='Zombowl' startx")
|
menu.add_item("Arcade", "Zombowl", "GAME='Zombowl' startx")
|
||||||
menu.add_item("Arcade", "Kitchen's Sink", "GAME=\"Kitchen's Sink\" startx")
|
|
||||||
menu.add_item("Arcade", "Swamp", "GAME='Swamp' startx")
|
# Add Kitchen's Sink and Swamp only on x86_64
|
||||||
|
if platform.machine() == "x86_64":
|
||||||
|
menu.add_item("Arcade", "Kitchen's Sink", "GAME=\"Kitchen's Sink\" startx")
|
||||||
|
menu.add_item("Arcade", "Swamp", "GAME='Swamp' startx")
|
||||||
|
|
||||||
# Add board and card games section
|
# Add board and card games section
|
||||||
menu.add_section("Board and Card Games")
|
menu.add_section("Board and Card Games")
|
||||||
@@ -1009,6 +1012,8 @@ if __name__ == "__main__":
|
|||||||
# Add accessories section
|
# Add accessories section
|
||||||
menu.add_section("Accessories")
|
menu.add_section("Accessories")
|
||||||
menu.add_item("Accessories", "Music Player", "/usr/local/bin/music_player.py")
|
menu.add_item("Accessories", "Music Player", "/usr/local/bin/music_player.py")
|
||||||
|
menu.add_item("Accessories", "Local IP Address", "/usr/local/bin/ip_info.py local")
|
||||||
|
menu.add_item("Accessories", "Remote IP Address", "/usr/local/bin/ip_info.py remote")
|
||||||
menu.add_item("Accessories", "Web Browser", "GAME=Brave startx")
|
menu.add_item("Accessories", "Web Browser", "GAME=Brave startx")
|
||||||
|
|
||||||
# Add system section
|
# Add system section
|
||||||
|
|||||||
Executable
+185
@@ -0,0 +1,185 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# IP Address Information Tool for Stormux
|
||||||
|
# Provides local and remote IP addresses with speech-friendly formatting
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
import re
|
||||||
|
import socket
|
||||||
|
import urllib.request
|
||||||
|
import urllib.error
|
||||||
|
import speechd
|
||||||
|
|
||||||
|
def init_speech():
|
||||||
|
"""Initialize speech client"""
|
||||||
|
try:
|
||||||
|
client = speechd.SSIPClient('ip_info')
|
||||||
|
client.set_priority(speechd.Priority.IMPORTANT)
|
||||||
|
client.set_punctuation(speechd.PunctuationMode.SOME)
|
||||||
|
return client
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Could not initialize speech: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def speak(client, text):
|
||||||
|
"""Speak text using speech client"""
|
||||||
|
if client:
|
||||||
|
try:
|
||||||
|
client.speak(text)
|
||||||
|
except Exception:
|
||||||
|
print(text)
|
||||||
|
else:
|
||||||
|
print(text)
|
||||||
|
|
||||||
|
def format_ip_for_speech(ip_address):
|
||||||
|
"""Format IP address for clear speech synthesis"""
|
||||||
|
if not ip_address:
|
||||||
|
return "No IP address found"
|
||||||
|
|
||||||
|
# Split IP into parts and replace dots with "dot"
|
||||||
|
parts = ip_address.split('.')
|
||||||
|
if len(parts) != 4:
|
||||||
|
return ip_address # Return as-is if not a standard IPv4
|
||||||
|
|
||||||
|
# Join with " dot " and add spaces between digits for clarity
|
||||||
|
formatted_parts = []
|
||||||
|
for part in parts:
|
||||||
|
# Add spaces between digits for better speech clarity
|
||||||
|
spaced_digits = ' '.join(part)
|
||||||
|
formatted_parts.append(spaced_digits)
|
||||||
|
|
||||||
|
return ' dot '.join(formatted_parts)
|
||||||
|
|
||||||
|
def get_local_ip():
|
||||||
|
"""Get the local IP address using multiple methods"""
|
||||||
|
|
||||||
|
# Method 1: Try to connect to a remote host to determine local IP
|
||||||
|
try:
|
||||||
|
# Create a socket and connect to a remote address
|
||||||
|
# This doesn't actually send data, just determines routing
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
sock.connect(("8.8.8.8", 80))
|
||||||
|
local_ip = sock.getsockname()[0]
|
||||||
|
sock.close()
|
||||||
|
|
||||||
|
# Validate it's not a loopback address
|
||||||
|
if not local_ip.startswith('127.'):
|
||||||
|
return local_ip
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Method 2: Parse ip route command output
|
||||||
|
try:
|
||||||
|
result = subprocess.run(['ip', 'route', 'get', '8.8.8.8'],
|
||||||
|
capture_output=True, text=True, check=True)
|
||||||
|
|
||||||
|
# Look for "src" in the output
|
||||||
|
match = re.search(r'src\s+(\d+\.\d+\.\d+\.\d+)', result.stdout)
|
||||||
|
if match:
|
||||||
|
return match.group(1)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Method 3: Parse ip addr show output for common network interfaces
|
||||||
|
try:
|
||||||
|
result = subprocess.run(['ip', 'addr', 'show'],
|
||||||
|
capture_output=True, text=True, check=True)
|
||||||
|
|
||||||
|
# Look for inet addresses that are not loopback
|
||||||
|
# Common patterns: 192.168.x.x, 10.x.x.x, 172.16-31.x.x
|
||||||
|
pattern = r'inet\s+(\d+\.\d+\.\d+\.\d+)/\d+'
|
||||||
|
matches = re.findall(pattern, result.stdout)
|
||||||
|
|
||||||
|
for ip in matches:
|
||||||
|
# Skip loopback
|
||||||
|
if ip.startswith('127.'):
|
||||||
|
continue
|
||||||
|
# Prefer common private network ranges
|
||||||
|
if (ip.startswith('192.168.') or
|
||||||
|
ip.startswith('10.') or
|
||||||
|
re.match(r'^172\.(1[6-9]|2[0-9]|3[01])\.', ip)):
|
||||||
|
return ip
|
||||||
|
|
||||||
|
# If no private IPs found, return the first non-loopback
|
||||||
|
for ip in matches:
|
||||||
|
if not ip.startswith('127.'):
|
||||||
|
return ip
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Method 4: Fallback using hostname
|
||||||
|
try:
|
||||||
|
hostname = socket.gethostname()
|
||||||
|
return socket.gethostbyname(hostname)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_remote_ip():
|
||||||
|
"""Get the remote/public IP address"""
|
||||||
|
services = [
|
||||||
|
'https://icanhazip.com',
|
||||||
|
'https://ipecho.net/plain',
|
||||||
|
'https://ifconfig.me/ip',
|
||||||
|
'https://api.ipify.org'
|
||||||
|
]
|
||||||
|
|
||||||
|
for service in services:
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(service, timeout=10) as response:
|
||||||
|
ip = response.read().decode('utf-8').strip()
|
||||||
|
# Validate it looks like an IP address
|
||||||
|
if re.match(r'^\d+\.\d+\.\d+\.\d+$', ip):
|
||||||
|
return ip
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) != 2 or sys.argv[1] not in ['local', 'remote']:
|
||||||
|
print("Usage: ip_info.py [local|remote]")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
mode = sys.argv[1]
|
||||||
|
speech_client = init_speech()
|
||||||
|
|
||||||
|
if mode == 'local':
|
||||||
|
print("Getting local IP address...")
|
||||||
|
ip = get_local_ip()
|
||||||
|
if ip:
|
||||||
|
formatted_ip = format_ip_for_speech(ip)
|
||||||
|
message = f"Local IP address: {formatted_ip}"
|
||||||
|
speak(speech_client, message)
|
||||||
|
print(f"Local IP: {ip}")
|
||||||
|
else:
|
||||||
|
message = "Could not determine local IP address"
|
||||||
|
speak(speech_client, message)
|
||||||
|
print(message)
|
||||||
|
|
||||||
|
elif mode == 'remote':
|
||||||
|
print("Getting remote IP address...")
|
||||||
|
ip = get_remote_ip()
|
||||||
|
if ip:
|
||||||
|
formatted_ip = format_ip_for_speech(ip)
|
||||||
|
message = f"Remote IP address: {formatted_ip}"
|
||||||
|
speak(speech_client, message)
|
||||||
|
print(f"Remote IP: {ip}")
|
||||||
|
else:
|
||||||
|
message = "Could not determine remote IP address. Check internet connection."
|
||||||
|
speak(speech_client, message)
|
||||||
|
print(message)
|
||||||
|
|
||||||
|
# Clean up speech client
|
||||||
|
if speech_client:
|
||||||
|
try:
|
||||||
|
speech_client.close()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user