Add web interface control for greeting delay
- Move greeting_delay from system config to user runtime config - Add GET/POST API endpoints at /api/greeting_delay - Add delay slider to web interface (0-10 seconds range) - Implement debounced slider updates (300ms delay) - Update visual gradient on slider movement - Display current delay value in seconds - Allow greeting delay adjustment without editing config files 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -105,16 +105,19 @@ class RotaryPhone:
|
||||
"active_greeting": SYS_CONFIG['system']['active_greeting'],
|
||||
"extra_button_sound": SYS_CONFIG['system'].get('extra_button_sound', 'button_sound.wav'),
|
||||
"greetings": [],
|
||||
"volume": SYS_CONFIG['system']['volume']
|
||||
"volume": SYS_CONFIG['system']['volume'],
|
||||
"greeting_delay": SYS_CONFIG['system'].get('greeting_delay_seconds', 0)
|
||||
}
|
||||
|
||||
if os.path.exists(USER_CONFIG_FILE):
|
||||
try:
|
||||
with open(USER_CONFIG_FILE, 'r') as f:
|
||||
config = json.load(f)
|
||||
# Ensure volume key exists
|
||||
# Ensure required keys exist
|
||||
if "volume" not in config:
|
||||
config["volume"] = SYS_CONFIG['system']['volume']
|
||||
if "greeting_delay" not in config:
|
||||
config["greeting_delay"] = SYS_CONFIG['system'].get('greeting_delay_seconds', 0)
|
||||
return config
|
||||
except:
|
||||
pass
|
||||
@@ -156,6 +159,17 @@ class RotaryPhone:
|
||||
def get_volume(self):
|
||||
"""Get current volume setting"""
|
||||
return self.config.get("volume", 70)
|
||||
|
||||
def set_greeting_delay(self, delay):
|
||||
"""Set greeting delay in seconds (0-10)"""
|
||||
delay = max(0, min(10, int(delay))) # Clamp between 0-10
|
||||
self.config["greeting_delay"] = delay
|
||||
self.save_config()
|
||||
return delay
|
||||
|
||||
def get_greeting_delay(self):
|
||||
"""Get current greeting delay"""
|
||||
return self.config.get("greeting_delay", 0)
|
||||
|
||||
def generate_default_dialtone(self):
|
||||
"""Generate a classic dial tone (350Hz + 440Hz) and save as default"""
|
||||
@@ -349,7 +363,7 @@ class RotaryPhone:
|
||||
print("\n=== Handset picked up ===")
|
||||
|
||||
# Apply greeting delay if configured
|
||||
greeting_delay = SYS_CONFIG['system'].get('greeting_delay_seconds', 0)
|
||||
greeting_delay = self.get_greeting_delay()
|
||||
if greeting_delay > 0:
|
||||
print(f"Waiting {greeting_delay} seconds before greeting...")
|
||||
time.sleep(greeting_delay)
|
||||
@@ -390,6 +404,7 @@ def index():
|
||||
active_greeting = phone.config.get("active_greeting", "dialtone.wav")
|
||||
extra_button_sound = phone.config.get("extra_button_sound", "button_sound.wav")
|
||||
volume = phone.get_volume()
|
||||
greeting_delay = phone.get_greeting_delay()
|
||||
|
||||
return render_template('index.html',
|
||||
recordings=recordings,
|
||||
@@ -398,7 +413,8 @@ def index():
|
||||
extra_button_sound=extra_button_sound,
|
||||
extra_button_enabled=EXTRA_BUTTON_ENABLED,
|
||||
status=status,
|
||||
volume=volume)
|
||||
volume=volume,
|
||||
greeting_delay=greeting_delay)
|
||||
|
||||
@app.route('/api/status')
|
||||
def api_status():
|
||||
@@ -428,6 +444,19 @@ def api_set_volume():
|
||||
new_volume = phone.set_volume(volume)
|
||||
return jsonify({"success": True, "volume": new_volume})
|
||||
|
||||
@app.route('/api/greeting_delay', methods=['GET'])
|
||||
def api_get_greeting_delay():
|
||||
"""Get current greeting delay setting"""
|
||||
return jsonify({"delay": phone.get_greeting_delay()})
|
||||
|
||||
@app.route('/api/greeting_delay', methods=['POST'])
|
||||
def api_set_greeting_delay():
|
||||
"""Set greeting delay in seconds"""
|
||||
data = request.get_json()
|
||||
delay = data.get('delay', 0)
|
||||
new_delay = phone.set_greeting_delay(delay)
|
||||
return jsonify({"success": True, "delay": new_delay})
|
||||
|
||||
@app.route('/upload_greeting', methods=['POST'])
|
||||
def upload_greeting():
|
||||
"""Upload a new greeting message"""
|
||||
@@ -1065,10 +1094,13 @@ if __name__ == "__main__":
|
||||
<button class="btn btn-secondary" onclick="refreshStatus()">🔄 Refresh</button>
|
||||
</div>
|
||||
|
||||
<!-- Volume Control Card -->
|
||||
<!-- Volume & Delay Control Card -->
|
||||
<div class="card">
|
||||
<h2>🔊 Volume Control</h2>
|
||||
<div style="padding: 20px;">
|
||||
<h2>🔊 Volume & Delay Control</h2>
|
||||
|
||||
<!-- Volume Control -->
|
||||
<div style="padding: 20px; border-bottom: 1px solid #e5e7eb;">
|
||||
<h3 style="margin: 0 0 15px 0; font-size: 1.1em; color: #333;">Volume</h3>
|
||||
<div style="display: flex; align-items: center; gap: 20px;">
|
||||
<span style="font-size: 1.5em;">🔇</span>
|
||||
<input type="range" id="volume-slider" min="0" max="100" value="{{ volume }}"
|
||||
@@ -1076,8 +1108,23 @@ if __name__ == "__main__":
|
||||
<span style="font-size: 1.5em;">🔊</span>
|
||||
<span id="volume-display" style="font-weight: bold; min-width: 50px; text-align: center; font-size: 1.2em;">{{ volume }}%</span>
|
||||
</div>
|
||||
<p style="margin-top: 15px; color: #6b7280; font-size: 0.9em; text-align: center;">
|
||||
Adjust the playback volume for greeting messages
|
||||
<p style="margin-top: 10px; color: #6b7280; font-size: 0.85em; text-align: center;">
|
||||
Playback volume for greeting messages
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Greeting Delay Control -->
|
||||
<div style="padding: 20px;">
|
||||
<h3 style="margin: 0 0 15px 0; font-size: 1.1em; color: #333;">Greeting Delay</h3>
|
||||
<div style="display: flex; align-items: center; gap: 20px;">
|
||||
<span style="font-size: 1.5em;">⏱️</span>
|
||||
<input type="range" id="delay-slider" min="0" max="10" value="{{ greeting_delay }}"
|
||||
style="flex: 1; height: 8px; border-radius: 5px; outline: none; background: linear-gradient(to right, #667eea 0%, #667eea {{ greeting_delay * 10 }}%, #ddd {{ greeting_delay * 10 }}%, #ddd 100%);">
|
||||
<span style="font-size: 1.5em;">⏰</span>
|
||||
<span id="delay-display" style="font-weight: bold; min-width: 50px; text-align: center; font-size: 1.2em;">{{ greeting_delay }}s</span>
|
||||
</div>
|
||||
<p style="margin-top: 10px; color: #6b7280; font-size: 0.85em; text-align: center;">
|
||||
Delay before greeting plays after pickup (0-10 seconds)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1244,6 +1291,7 @@ if __name__ == "__main__":
|
||||
<script>
|
||||
let selectedFiles = null;
|
||||
let volumeUpdateTimer = null;
|
||||
let delayUpdateTimer = null;
|
||||
|
||||
// Volume control
|
||||
const volumeSlider = document.getElementById('volume-slider');
|
||||
@@ -1280,6 +1328,42 @@ if __name__ == "__main__":
|
||||
.catch(error => console.error('Error updating volume:', error));
|
||||
}
|
||||
|
||||
// Greeting Delay control
|
||||
const delaySlider = document.getElementById('delay-slider');
|
||||
const delayDisplay = document.getElementById('delay-display');
|
||||
|
||||
delaySlider.addEventListener('input', function() {
|
||||
const value = this.value;
|
||||
delayDisplay.textContent = value + 's';
|
||||
|
||||
// Update slider background gradient (0-10 range = 0-100%)
|
||||
const percent = (value / 10) * 100;
|
||||
this.style.background = `linear-gradient(to right, #667eea 0%, #667eea ${percent}%, #ddd ${percent}%, #ddd 100%)`;
|
||||
|
||||
// Debounce API call
|
||||
clearTimeout(delayUpdateTimer);
|
||||
delayUpdateTimer = setTimeout(() => {
|
||||
updateGreetingDelay(value);
|
||||
}, 300);
|
||||
});
|
||||
|
||||
function updateGreetingDelay(delay) {
|
||||
fetch('/api/greeting_delay', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ delay: parseInt(delay) })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
console.log('Greeting delay updated to ' + data.delay + 's');
|
||||
}
|
||||
})
|
||||
.catch(error => console.error('Error updating delay:', error));
|
||||
}
|
||||
|
||||
function handleFileSelect(input) {
|
||||
if (input.files && input.files.length > 0) {
|
||||
selectedFiles = input.files;
|
||||
|
||||
Reference in New Issue
Block a user