Version 1.0.2 terminalphone.sh
This commit is contained in:
parent
f9ae1049f6
commit
51d26f0a30
1 changed files with 1 additions and 147 deletions
148
terminalphone.sh
148
terminalphone.sh
|
|
@ -9,7 +9,7 @@ set -euo pipefail
|
||||||
# CONFIGURATION
|
# CONFIGURATION
|
||||||
#=============================================================================
|
#=============================================================================
|
||||||
APP_NAME="TerminalPhone"
|
APP_NAME="TerminalPhone"
|
||||||
VERSION="1.0.1"
|
VERSION="1.0.2"
|
||||||
BASE_DIR="$(dirname "$(readlink -f "$0")")"
|
BASE_DIR="$(dirname "$(readlink -f "$0")")"
|
||||||
DATA_DIR="$BASE_DIR/.terminalphone"
|
DATA_DIR="$BASE_DIR/.terminalphone"
|
||||||
TOR_DIR="$DATA_DIR/tor_data"
|
TOR_DIR="$DATA_DIR/tor_data"
|
||||||
|
|
@ -49,7 +49,6 @@ BLINK='\033[5m'
|
||||||
NC='\033[0m' # No Color
|
NC='\033[0m' # No Color
|
||||||
BG_RED='\033[41m'
|
BG_RED='\033[41m'
|
||||||
BG_GREEN='\033[42m'
|
BG_GREEN='\033[42m'
|
||||||
BG_BLUE='\033[44m'
|
|
||||||
TOR_PURPLE='\033[38;2;125;70;152m'
|
TOR_PURPLE='\033[38;2;125;70;152m'
|
||||||
|
|
||||||
# Platform detection
|
# Platform detection
|
||||||
|
|
@ -60,7 +59,6 @@ fi
|
||||||
|
|
||||||
# State
|
# State
|
||||||
TOR_PID=""
|
TOR_PID=""
|
||||||
LISTENER_PID=""
|
|
||||||
CALL_ACTIVE=0
|
CALL_ACTIVE=0
|
||||||
ORIGINAL_STTY=""
|
ORIGINAL_STTY=""
|
||||||
|
|
||||||
|
|
@ -567,26 +565,7 @@ audio_play() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Record a chunk of audio, encode to opus, return the file path
|
|
||||||
record_chunk() {
|
|
||||||
local _id=$(uid)
|
|
||||||
local raw_file="$AUDIO_DIR/rec_${_id}.raw"
|
|
||||||
local opus_file="$AUDIO_DIR/rec_${_id}.opus"
|
|
||||||
|
|
||||||
# Record raw audio
|
|
||||||
audio_record "$raw_file" "$CHUNK_DURATION"
|
|
||||||
|
|
||||||
# Encode to opus
|
|
||||||
if [ -s "$raw_file" ]; then
|
|
||||||
opusenc --raw --raw-rate "$SAMPLE_RATE" --raw-chan 1 \
|
|
||||||
--bitrate "$OPUS_BITRATE" --framesize "$OPUS_FRAMESIZE" \
|
|
||||||
--speech --quiet \
|
|
||||||
"$raw_file" "$opus_file" 2>/dev/null
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -f "$raw_file"
|
|
||||||
echo "$opus_file"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Play an opus file
|
# Play an opus file
|
||||||
play_chunk() {
|
play_chunk() {
|
||||||
|
|
@ -607,132 +586,7 @@ play_chunk() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
#=============================================================================
|
|
||||||
# PROTOCOL — FRAMED MESSAGES
|
|
||||||
#=============================================================================
|
|
||||||
# Message format: [1 byte type][4 bytes length (big-endian)][payload]
|
|
||||||
# Types: 0x01 = voice data, 0x02 = PTT start, 0x03 = PTT stop, 0x04 = ping, 0x05 = text
|
|
||||||
|
|
||||||
PROTO_VOICE=1
|
|
||||||
PROTO_PTT_START=2
|
|
||||||
PROTO_PTT_STOP=3
|
|
||||||
PROTO_PING=4
|
|
||||||
PROTO_TEXT=5
|
|
||||||
|
|
||||||
# Send a framed message over the connection fd
|
|
||||||
send_message() {
|
|
||||||
local msg_type="$1"
|
|
||||||
local payload_file="$2" # file containing payload, or empty
|
|
||||||
local fd="$3"
|
|
||||||
|
|
||||||
local payload_len=0
|
|
||||||
if [ -n "$payload_file" ] && [ -f "$payload_file" ]; then
|
|
||||||
payload_len=$(stat -c%s "$payload_file" 2>/dev/null || echo 0)
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Write header: type (1 byte) + length (4 bytes big-endian)
|
|
||||||
printf "\\x$(printf '%02x' "$msg_type")" >&"$fd"
|
|
||||||
printf "\\x$(printf '%02x' $(( (payload_len >> 24) & 0xFF )))" >&"$fd"
|
|
||||||
printf "\\x$(printf '%02x' $(( (payload_len >> 16) & 0xFF )))" >&"$fd"
|
|
||||||
printf "\\x$(printf '%02x' $(( (payload_len >> 8) & 0xFF )))" >&"$fd"
|
|
||||||
printf "\\x$(printf '%02x' $(( payload_len & 0xFF )))" >&"$fd"
|
|
||||||
|
|
||||||
# Write payload
|
|
||||||
if [ "$payload_len" -gt 0 ]; then
|
|
||||||
cat "$payload_file" >&"$fd"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
#=============================================================================
|
|
||||||
# CONNECTION HANDLER
|
|
||||||
#=============================================================================
|
|
||||||
|
|
||||||
# Background process: handle receiving data from remote
|
|
||||||
receive_loop() {
|
|
||||||
local conn_fd="$1"
|
|
||||||
mkdir -p "$AUDIO_DIR"
|
|
||||||
|
|
||||||
while [ -f "$CONNECTED_FLAG" ]; do
|
|
||||||
# Read message header (5 bytes: 1 type + 4 length)
|
|
||||||
local header
|
|
||||||
header=$(dd bs=1 count=5 <&"$conn_fd" 2>/dev/null | xxd -p)
|
|
||||||
|
|
||||||
if [ -z "$header" ] || [ ${#header} -lt 10 ]; then
|
|
||||||
sleep 0.1
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
local msg_type=$((16#${header:0:2}))
|
|
||||||
local payload_len=$((16#${header:2:8}))
|
|
||||||
|
|
||||||
case $msg_type in
|
|
||||||
$PROTO_VOICE)
|
|
||||||
if [ "$payload_len" -gt 0 ]; then
|
|
||||||
local _rid=$(uid)
|
|
||||||
local enc_file="$AUDIO_DIR/recv_enc_${_rid}.opus"
|
|
||||||
local dec_file="$AUDIO_DIR/recv_${_rid}.opus"
|
|
||||||
dd bs=1 count="$payload_len" <&"$conn_fd" > "$enc_file" 2>/dev/null
|
|
||||||
if decrypt_file "$enc_file" "$dec_file"; then
|
|
||||||
play_chunk "$dec_file"
|
|
||||||
fi
|
|
||||||
rm -f "$enc_file" "$dec_file"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
$PROTO_PTT_START)
|
|
||||||
echo -e "\r${BG_GREEN}${WHITE} ▶ REMOTE SPEAKING ${NC} " >&2
|
|
||||||
;;
|
|
||||||
$PROTO_PTT_STOP)
|
|
||||||
echo -e "\r${DIM} ■ Remote idle ${NC} " >&2
|
|
||||||
;;
|
|
||||||
$PROTO_PING)
|
|
||||||
# Respond with ping
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# Background process: handle sending based on PTT state
|
|
||||||
transmit_loop() {
|
|
||||||
local conn_fd="$1"
|
|
||||||
local was_pressed=0
|
|
||||||
mkdir -p "$AUDIO_DIR"
|
|
||||||
|
|
||||||
while [ -f "$CONNECTED_FLAG" ]; do
|
|
||||||
if [ -f "$PTT_FLAG" ]; then
|
|
||||||
if [ $was_pressed -eq 0 ]; then
|
|
||||||
# PTT just pressed — notify remote
|
|
||||||
was_pressed=1
|
|
||||||
local empty_file="$AUDIO_DIR/empty_$(uid)"
|
|
||||||
touch "$empty_file"
|
|
||||||
send_message $PROTO_PTT_START "$empty_file" "$conn_fd" 2>/dev/null || true
|
|
||||||
rm -f "$empty_file"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Record a chunk, encrypt, and send
|
|
||||||
local opus_file
|
|
||||||
opus_file=$(record_chunk)
|
|
||||||
if [ -f "$opus_file" ]; then
|
|
||||||
local enc_file="$AUDIO_DIR/send_enc_$(uid).opus"
|
|
||||||
if encrypt_file "$opus_file" "$enc_file"; then
|
|
||||||
send_message $PROTO_VOICE "$enc_file" "$conn_fd" 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
rm -f "$opus_file" "$enc_file"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
if [ $was_pressed -eq 1 ]; then
|
|
||||||
# PTT just released — notify remote
|
|
||||||
was_pressed=0
|
|
||||||
local empty_file="$AUDIO_DIR/empty_$(uid)"
|
|
||||||
touch "$empty_file"
|
|
||||||
send_message $PROTO_PTT_STOP "$empty_file" "$conn_fd" 2>/dev/null || true
|
|
||||||
rm -f "$empty_file"
|
|
||||||
fi
|
|
||||||
sleep 0.1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
#=============================================================================
|
#=============================================================================
|
||||||
# CALL CLEANUP — RESET EVERYTHING TO FRESH STATE
|
# CALL CLEANUP — RESET EVERYTHING TO FRESH STATE
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue