| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- #include "rtsp_conn.h"
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include "audio_receiver.h"
- #include "ptp_clock.h"
- #include "settings.h"
- rtsp_conn_t *rtsp_conn_create(void) {
- rtsp_conn_t *conn = calloc(1, sizeof(rtsp_conn_t));
- if (!conn) {
- return NULL;
- }
- // Load saved volume or use default
- float saved_volume;
- if (settings_get_volume(&saved_volume) == ESP_OK) {
- conn->volume_db = saved_volume;
- // Apply volume curve
- if (saved_volume <= -30.0f) {
- conn->volume_q15 = 0;
- } else if (saved_volume >= 0.0f) {
- conn->volume_q15 = 32768;
- } else {
- float normalized = (saved_volume + 30.0f) / 30.0f;
- conn->volume_q15 = (int32_t)(normalized * normalized * 32768.0f);
- }
- } else {
- conn->volume_db = -15.0f; // Half volume (midpoint of -30..0 dB range)
- float normalized = (conn->volume_db + 30.0f) / 30.0f;
- conn->volume_q15 = (int32_t)(normalized * normalized * 32768.0f);
- }
- conn->data_socket = -1;
- conn->control_socket = -1;
- conn->event_socket = -1;
- return conn;
- }
- void rtsp_conn_free(rtsp_conn_t *conn) {
- if (!conn) {
- return;
- }
- // Persist volume at disconnect
- settings_persist_volume();
- // Cleanup any resources
- rtsp_conn_cleanup(conn);
- // Free HAP session if present
- if (conn->hap_session) {
- hap_session_free(conn->hap_session);
- conn->hap_session = NULL;
- }
- free(conn);
- }
- void rtsp_conn_reset_stream(rtsp_conn_t *conn) {
- if (!conn) {
- return;
- }
- // Reset stream state but keep session alive
- conn->stream_active = false;
- conn->stream_paused = true; // Paused, not fully torn down
- // Keep ports allocated for quick resume
- // Don't clear: data_port, control_port, timing_port, event_port
- }
- void rtsp_conn_cleanup(rtsp_conn_t *conn) {
- if (!conn) {
- return;
- }
- // Note: audio_receiver_stop() is NOT called here — it is a global operation
- // and must be managed by the caller (rtsp_server cleanup / handle_teardown)
- // to avoid killing a new session's audio during client replacement.
- // Close sockets
- if (conn->data_socket >= 0) {
- close(conn->data_socket);
- conn->data_socket = -1;
- }
- if (conn->control_socket >= 0) {
- close(conn->control_socket);
- conn->control_socket = -1;
- }
- if (conn->event_socket >= 0) {
- close(conn->event_socket);
- conn->event_socket = -1;
- }
- // Reset stream state
- conn->stream_active = false;
- conn->stream_paused = false;
- conn->data_port = 0;
- conn->control_port = 0;
- conn->timing_port = 0;
- conn->event_port = 0;
- conn->buffered_port = 0;
- // Clear PTP clock for fresh sync on next connection
- ptp_clock_clear();
- // Reset encryption state
- conn->encrypted_mode = false;
- }
- void rtsp_conn_set_volume(rtsp_conn_t *conn, float volume_db) {
- if (!conn) {
- return;
- }
- conn->volume_db = volume_db;
- // AirPlay volume: 0 dB = max, -30 dB = mute
- // Use squared curve for better perceptual control
- if (volume_db <= -30.0f) {
- conn->volume_q15 = 0;
- } else if (volume_db >= 0.0f) {
- conn->volume_q15 = 32768;
- } else {
- // Map -30..0 to 0..1, then square for perceptual curve
- float normalized = (volume_db + 30.0f) / 30.0f;
- float curved = normalized * normalized;
- conn->volume_q15 = (int32_t)(curved * 32768.0f);
- }
- // Update cached volume + DAC (NVS persisted at disconnect)
- settings_set_volume(volume_db);
- }
- int32_t rtsp_conn_get_volume_q15(rtsp_conn_t *conn) {
- if (!conn) {
- return 32768; // Default full volume
- }
- return conn->volume_q15;
- }
|