diff --git a/config.example.json b/config.example.json index cda5fac..c042506 100644 --- a/config.example.json +++ b/config.example.json @@ -38,6 +38,9 @@ "beep_sound": "beep.wav", "beep_enabled": true, "greeting_delay_seconds": 0, - "volume": 70 + "volume": 70, + "volume_greeting": 70, + "volume_button": 70, + "volume_beep": 70 } } diff --git a/rotary_phone_web.py b/rotary_phone_web.py index 6257f15..0d65d39 100644 --- a/rotary_phone_web.py +++ b/rotary_phone_web.py @@ -81,7 +81,7 @@ BACKUP_ON_WRITE = BACKUP_CONFIG.get('backup_on_write', True) WEB_PORT = SYS_CONFIG['web']['port'] # Template version - increment this when HTML template changes -TEMPLATE_VERSION = "1.6.0" # Updated: Added rename functionality for recordings +TEMPLATE_VERSION = "1.7.0" # Updated: Separate volume controls for greeting, button, and beep # Flask app app = Flask(__name__) @@ -264,6 +264,9 @@ class RotaryPhone: "beep_enabled": SYS_CONFIG['system'].get('beep_enabled', True), "greetings": [], "volume": SYS_CONFIG['system']['volume'], + "volume_greeting": SYS_CONFIG['system'].get('volume_greeting', 70), + "volume_button": SYS_CONFIG['system'].get('volume_button', 70), + "volume_beep": SYS_CONFIG['system'].get('volume_beep', 70), "greeting_delay": SYS_CONFIG['system'].get('greeting_delay_seconds', 0) } @@ -274,6 +277,12 @@ class RotaryPhone: # Ensure required keys exist if "volume" not in config: config["volume"] = SYS_CONFIG['system']['volume'] + if "volume_greeting" not in config: + config["volume_greeting"] = SYS_CONFIG['system'].get('volume_greeting', 70) + if "volume_button" not in config: + config["volume_button"] = SYS_CONFIG['system'].get('volume_button', 70) + if "volume_beep" not in config: + config["volume_beep"] = SYS_CONFIG['system'].get('volume_beep', 70) if "greeting_delay" not in config: config["greeting_delay"] = SYS_CONFIG['system'].get('greeting_delay_seconds', 0) if "beep_enabled" not in config: @@ -341,6 +350,39 @@ class RotaryPhone: """Get current volume setting""" return self.config.get("volume", 70) + def set_volume_greeting(self, volume): + """Set greeting volume (0-100)""" + volume = max(0, min(100, int(volume))) + self.config["volume_greeting"] = volume + self.save_config() + return volume + + def get_volume_greeting(self): + """Get greeting volume setting""" + return self.config.get("volume_greeting", 70) + + def set_volume_button(self, volume): + """Set button sound volume (0-100)""" + volume = max(0, min(100, int(volume))) + self.config["volume_button"] = volume + self.save_config() + return volume + + def get_volume_button(self): + """Get button sound volume setting""" + return self.config.get("volume_button", 70) + + def set_volume_beep(self, volume): + """Set beep sound volume (0-100)""" + volume = max(0, min(100, int(volume))) + self.config["volume_beep"] = volume + self.save_config() + return volume + + def get_volume_beep(self): + """Get beep sound volume setting""" + return self.config.get("volume_beep", 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 @@ -398,13 +440,14 @@ class RotaryPhone: wf.close() print(f"Default beep sound saved to {beep_file} ({RATE}Hz, 16-bit)") - def play_sound_file(self, filepath, check_hook_status=True): + def play_sound_file(self, filepath, check_hook_status=True, volume_override=None): """Play a WAV file with volume control Args: filepath: Path to WAV file check_hook_status: If True, only play while off-hook (for greeting). If False, play completely regardless of hook (for button) + volume_override: Override volume (0-100), or None to use default volume """ if not os.path.exists(filepath): print(f"Sound file not found: {filepath}") @@ -434,7 +477,7 @@ class RotaryPhone: ) # Get volume multiplier (0.0 to 1.0) - volume = self.get_volume() / 100.0 + volume = (volume_override if volume_override is not None else self.get_volume()) / 100.0 # Play the sound with volume control data = wf.readframes(CHUNK) @@ -607,8 +650,9 @@ class RotaryPhone: frames_per_buffer=CHUNK ) - # Get volume multiplier - volume = self.get_volume() / 100.0 + # Get button volume multiplier + button_volume = self.config.get("volume_button", 70) + volume = button_volume / 100.0 print(f"[BUTTON] Volume: {int(volume * 100)}%") # Play the sound @@ -680,13 +724,15 @@ class RotaryPhone: # Play active greeting message greeting_file = self.get_active_greeting_path() - self.play_sound_file(greeting_file) + greeting_volume = self.config.get("volume_greeting", 70) + self.play_sound_file(greeting_file, volume_override=greeting_volume) # Play beep sound to indicate recording will start if self.phone_status == "off_hook" and self.is_beep_enabled(): beep_file = self.get_beep_sound_path() + beep_volume = self.config.get("volume_beep", 70) if os.path.exists(beep_file): - self.play_sound_file(beep_file) + self.play_sound_file(beep_file, volume_override=beep_volume) # Start recording if self.phone_status == "off_hook": # Still off hook after sound @@ -722,6 +768,9 @@ def index(): beep_sound = phone.config.get("beep_sound", "beep.wav") beep_enabled = phone.is_beep_enabled() volume = phone.get_volume() + volume_greeting = phone.get_volume_greeting() + volume_button = phone.get_volume_button() + volume_beep = phone.get_volume_beep() greeting_delay = phone.get_greeting_delay() return render_template('index.html', @@ -734,6 +783,9 @@ def index(): extra_button_enabled=EXTRA_BUTTON_ENABLED, status=status, volume=volume, + volume_greeting=volume_greeting, + volume_button=volume_button, + volume_beep=volume_beep, greeting_delay=greeting_delay) @app.route('/api/status') @@ -764,6 +816,45 @@ def api_set_volume(): new_volume = phone.set_volume(volume) return jsonify({"success": True, "volume": new_volume}) +@app.route('/api/volume/greeting', methods=['GET']) +def api_get_volume_greeting(): + """Get greeting volume setting""" + return jsonify({"volume": phone.get_volume_greeting()}) + +@app.route('/api/volume/greeting', methods=['POST']) +def api_set_volume_greeting(): + """Set greeting volume level""" + data = request.get_json() + volume = data.get('volume', 70) + new_volume = phone.set_volume_greeting(volume) + return jsonify({"success": True, "volume": new_volume}) + +@app.route('/api/volume/button', methods=['GET']) +def api_get_volume_button(): + """Get button sound volume setting""" + return jsonify({"volume": phone.get_volume_button()}) + +@app.route('/api/volume/button', methods=['POST']) +def api_set_volume_button(): + """Set button sound volume level""" + data = request.get_json() + volume = data.get('volume', 70) + new_volume = phone.set_volume_button(volume) + return jsonify({"success": True, "volume": new_volume}) + +@app.route('/api/volume/beep', methods=['GET']) +def api_get_volume_beep(): + """Get beep sound volume setting""" + return jsonify({"volume": phone.get_volume_beep()}) + +@app.route('/api/volume/beep', methods=['POST']) +def api_set_volume_beep(): + """Set beep sound volume level""" + data = request.get_json() + volume = data.get('volume', 70) + new_volume = phone.set_volume_beep(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""" @@ -1606,19 +1697,45 @@ def main():
- Playback volume for greeting messages -