Fix WAV call recording/playback, ALSA call audio routing, and tracker ringtones
This commit is contained in:
@@ -196,7 +196,7 @@ All fifteen phone applications are compiled as shared-object plugins (`/usr/lib/
|
||||
|
||||
13. **Ringtones and ringer manager (`ringtones.so` / `xringtones`)**:
|
||||
- **Open**: select **Ringtones** from the System, Config, or Audio menu, or run `xringtones`.
|
||||
- **Controls**: preview built-in and user ringtones (`~/Ringtones/`, `~/Music/`, `/usr/share/sxmo/ringtones/`) at the configured ringtone volume with `*` or **Left softkey (`Play` / `Stop`)**, press `Return` to set the active ringtone, and switch to **`2:Settings`** to configure **Ringer Mode**, **Ring Volume** (`0%`–`100%`, also adjustable in **XDrawer**), **Ring Duration**, **Ring Loop Count**, and 3-level hardware **Vibrate Strength** (`Level 1` gentle `1400 mV`, `Level 2` medium `2100 mV`, `Level 3` strong `3100 mV`).
|
||||
- **Controls**: preview built-in, tracker module (`.mod`, `.xm`, `.it`, `.s3m`, etc.), and user ringtones (`~/Ringtones/`, `~/Music/`, `/usr/share/sxmo/ringtones/`, `/usr/share/sxmo/music/`) at the configured ringtone volume with `*` or **Left softkey (`Play` / `Stop`)**, press `Return` to set the active ringtone, and switch to **`2:Settings`** to configure **Ringer Mode**, **Ring Volume** (`0%`–`100%`, also adjustable in **XDrawer**), **Ring Duration**, **Ring Loop Count**, and 3-level hardware **Vibrate Strength** (`Level 1` gentle `1400 mV`, `Level 2` medium `2100 mV`, `Level 3` strong `3100 mV`).
|
||||
|
||||
14. **Desktop wallpaper manager (`wallpapers.so` / `xwallpapers` / `xbackground`)**:
|
||||
- **Open**: select **Wallpapers** from the System, Config, or Apps menu, or run `xwallpapers`.
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
monitor.alsa.rules = [
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
device.name = "alsa_card.comprC0"
|
||||
}
|
||||
]
|
||||
actions = {
|
||||
update-props = {
|
||||
device.disabled = true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
node.name = "~alsa_output.platform-7702000.*"
|
||||
},
|
||||
{
|
||||
node.name = "~alsa_output.platform-sound.*"
|
||||
},
|
||||
{
|
||||
node.name = "~alsa_input.platform-7702000.*"
|
||||
},
|
||||
{
|
||||
node.name = "~alsa_input.platform-sound.*"
|
||||
}
|
||||
]
|
||||
actions = {
|
||||
update-props = {
|
||||
audio.format = "S16LE"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,35 @@
|
||||
monitor.alsa.rules = [
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
device.name = "alsa_card.comprC0"
|
||||
}
|
||||
]
|
||||
actions = {
|
||||
update-props = {
|
||||
device.disabled = true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
node.name = "~alsa_output.platform-7702000.*"
|
||||
},
|
||||
{
|
||||
node.name = "~alsa_output.platform-sound.*"
|
||||
},
|
||||
{
|
||||
node.name = "~alsa_input.platform-7702000.*"
|
||||
},
|
||||
{
|
||||
node.name = "~alsa_input.platform-sound.*"
|
||||
}
|
||||
]
|
||||
actions = {
|
||||
update-props = {
|
||||
audio.format = "S16LE"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,35 @@
|
||||
monitor.alsa.rules = [
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
device.name = "alsa_card.comprC0"
|
||||
}
|
||||
]
|
||||
actions = {
|
||||
update-props = {
|
||||
device.disabled = true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
node.name = "~alsa_output.platform-7702000.*"
|
||||
},
|
||||
{
|
||||
node.name = "~alsa_output.platform-sound.*"
|
||||
},
|
||||
{
|
||||
node.name = "~alsa_input.platform-7702000.*"
|
||||
},
|
||||
{
|
||||
node.name = "~alsa_input.platform-sound.*"
|
||||
}
|
||||
]
|
||||
actions = {
|
||||
update-props = {
|
||||
audio.format = "S16LE"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -2,6 +2,8 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
# Copyright 2022 Sxmo Contributors
|
||||
|
||||
export PATH="${XDG_CONFIG_HOME:-$HOME/.config}/sxmo/hooks:/usr/share/sxmo/default_hooks:$PATH"
|
||||
|
||||
# shellcheck source=configs/default_hooks/sxmo_hook_icons.sh
|
||||
. sxmo_hook_icons.sh
|
||||
. sxmo_common.sh
|
||||
|
||||
@@ -1,31 +1,59 @@
|
||||
#!/bin/sh
|
||||
|
||||
export PATH="${XDG_CONFIG_HOME:-$HOME/.config}/sxmo/hooks:/usr/share/sxmo/default_hooks:$PATH"
|
||||
|
||||
# shellcheck source=scripts/core/sxmo_common.sh
|
||||
. sxmo_common.sh
|
||||
|
||||
enable_call_audio_mode() {
|
||||
if command -v amixer >/dev/null 2>&1; then
|
||||
amixer -c 0 sset 'SPK DAC Switch' off >/dev/null 2>&1 || true
|
||||
amixer -c 0 sset 'RX3 MIX1 INP1' 'ZERO' >/dev/null 2>&1 || true
|
||||
amixer -c 0 sset 'PRI_MI2S_RX Voice Mixer VoiceMMode1' on >/dev/null 2>&1 || true
|
||||
amixer -c 0 sset 'VoiceMMode1 Capture Mixer TERT_MI2S_TX' on >/dev/null 2>&1 || true
|
||||
amixer -c 0 sset 'MultiMedia2 Mixer TERT_MI2S_TX' on >/dev/null 2>&1 || true
|
||||
amixer -c 0 sset 'RX1 MIX1 INP1' 'RX1' >/dev/null 2>&1 || true
|
||||
amixer -c 0 sset 'RDAC2 MUX' 'RX1' >/dev/null 2>&1 || true
|
||||
amixer -c 0 sset 'EAR_S' 'Switch' >/dev/null 2>&1 || true
|
||||
amixer -c 0 sset 'CIC1 MUX' 'AMIC' >/dev/null 2>&1 || true
|
||||
amixer -c 0 sset 'DEC1 MUX' 'ADC1' >/dev/null 2>&1 || true
|
||||
amixer -c 0 sset 'ADC1 Volume' 100% >/dev/null 2>&1 || true
|
||||
amixer -c 0 sset 'ADC1 Volume' 6 >/dev/null 2>&1 || true
|
||||
amixer -c 0 sset 'RX1 Digital Volume' 84 >/dev/null 2>&1 || true
|
||||
fi
|
||||
sxmo_audio.sh device set Earpiece >/dev/null 2>&1 || true
|
||||
sxmo_log "Enabled ALSA voice call audio mode (Earpiece)."
|
||||
sxmo_hook_statusbar.sh volume >/dev/null 2>&1 || true
|
||||
return 0
|
||||
}
|
||||
|
||||
disable_call_audio_mode() {
|
||||
spk_vol=85
|
||||
if [ -r "${XDG_CONFIG_HOME:-$HOME/.config}/sxmo/speaker_vol" ]; then
|
||||
read -r spk_vol < "${XDG_CONFIG_HOME:-$HOME/.config}/sxmo/speaker_vol" 2>/dev/null || spk_vol=85
|
||||
fi
|
||||
case "$spk_vol" in ''|*[!0-9]*) spk_vol=85 ;; esac
|
||||
[ "$spk_vol" -gt 100 ] && spk_vol=100
|
||||
|
||||
pactl set-card-profile alsa_card.comprC0 off >/dev/null 2>&1 || true
|
||||
if ! pactl list sinks short 2>/dev/null | grep -q "Speaker"; then
|
||||
pactl set-card-profile alsa_card.platform-7702000.sound "HiFi (Mic1, Speaker)" >/dev/null 2>&1 || true
|
||||
fi
|
||||
if command -v amixer >/dev/null 2>&1; then
|
||||
amixer -c 0 sset 'PRI_MI2S_RX Voice Mixer VoiceMMode1' off >/dev/null 2>&1 || true
|
||||
amixer -c 0 sset 'VoiceMMode1 Capture Mixer TERT_MI2S_TX' off >/dev/null 2>&1 || true
|
||||
amixer -c 0 sset 'EAR_S' 'ZERO' >/dev/null 2>&1 || true
|
||||
amixer -c 0 sset 'RX1 MIX1 INP1' 'ZERO' >/dev/null 2>&1 || true
|
||||
amixer -c 0 sset 'RX3 MIX1 INP1' 'RX1' >/dev/null 2>&1 || true
|
||||
if [ "$spk_vol" -gt 0 ]; then
|
||||
rx3_hw=$(( 60 + spk_vol * 32 / 100 ))
|
||||
amixer -c 0 sset 'SPK DAC Switch' on >/dev/null 2>&1 || true
|
||||
amixer -c 0 sset 'RX3 Digital Volume' "$rx3_hw" >/dev/null 2>&1 || true
|
||||
else
|
||||
amixer -c 0 sset 'SPK DAC Switch' off >/dev/null 2>&1 || true
|
||||
amixer -c 0 sset 'RX3 Digital Volume' 0 >/dev/null 2>&1 || true
|
||||
fi
|
||||
fi
|
||||
sxmo_audio.sh device set Speaker >/dev/null 2>&1 || true
|
||||
wpctl set-mute @DEFAULT_AUDIO_SINK@ "$([ "$spk_vol" -le 0 ] && echo 1 || echo 0)" >/dev/null 2>&1 || true
|
||||
wpctl set-volume @DEFAULT_AUDIO_SINK@ "${spk_vol}%" >/dev/null 2>&1 || true
|
||||
sxmo_log "Disabled ALSA voice call audio mode (Speaker)."
|
||||
sxmo_hook_statusbar.sh volume >/dev/null 2>&1 || true
|
||||
return 0
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -84,10 +84,12 @@ ring() {
|
||||
ring_rx3=$(( 60 + SXMO_RINGVOL * 34 / 100 ))
|
||||
mpv_vol=$(( SXMO_RINGVOL * 130 / 100 ))
|
||||
amixer -c 0 cset "name='SPK DAC Switch'" 1 >/dev/null 2>&1 || true
|
||||
amixer -c 0 cset "name='RX3 MIX1 INP1'" 3 >/dev/null 2>&1 || true
|
||||
amixer -c 0 cset "name='RX3 Digital Volume'" "$ring_rx3" >/dev/null 2>&1 || true
|
||||
wpctl set-mute @DEFAULT_AUDIO_SINK@ 0 >/dev/null 2>&1 || true
|
||||
wpctl set-volume @DEFAULT_AUDIO_SINK@ 100% >/dev/null 2>&1 || true
|
||||
mpv --no-resume-playback --quiet --no-video \
|
||||
--ao=pipewire,pulse,alsa --audio-channels=stereo --audio-samplerate=48000 \
|
||||
--volume-max=150 --volume="$mpv_vol" \
|
||||
--loop="${SXMO_RINGNUMBER:-10}" "$SXMO_RINGTONE" >/dev/null &
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
monitor.alsa.rules = [
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
device.name = "alsa_card.comprC0"
|
||||
}
|
||||
]
|
||||
actions = {
|
||||
update-props = {
|
||||
device.disabled = true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
node.name = "~alsa_output.platform-7702000.*"
|
||||
},
|
||||
{
|
||||
node.name = "~alsa_output.platform-sound.*"
|
||||
},
|
||||
{
|
||||
node.name = "~alsa_input.platform-7702000.*"
|
||||
},
|
||||
{
|
||||
node.name = "~alsa_input.platform-sound.*"
|
||||
}
|
||||
]
|
||||
actions = {
|
||||
update-props = {
|
||||
audio.format = "S16LE"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -273,6 +273,18 @@ EOF
|
||||
|
||||
cat > "$ROOTFS/usr/share/wireplumber/wireplumber.conf.d/msm8916-s16le.conf" <<EOF
|
||||
monitor.alsa.rules = [
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
device.name = "alsa_card.comprC0"
|
||||
}
|
||||
]
|
||||
actions = {
|
||||
update-props = {
|
||||
device.disabled = true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
@@ -280,6 +292,12 @@ monitor.alsa.rules = [
|
||||
},
|
||||
{
|
||||
node.name = "~alsa_output.platform-sound.*"
|
||||
},
|
||||
{
|
||||
node.name = "~alsa_input.platform-7702000.*"
|
||||
},
|
||||
{
|
||||
node.name = "~alsa_input.platform-sound.*"
|
||||
}
|
||||
]
|
||||
actions = {
|
||||
|
||||
@@ -207,6 +207,61 @@ std::string getRecordingsDir() {
|
||||
return dir;
|
||||
}
|
||||
|
||||
void finalizeWavHeader(const std::string& path) {
|
||||
if (path.empty()) return;
|
||||
int fd = ::open(path.c_str(), O_RDWR);
|
||||
if (fd < 0) return;
|
||||
struct stat st {};
|
||||
if (::fstat(fd, &st) != 0 || st.st_size <= 44) {
|
||||
::close(fd);
|
||||
return;
|
||||
}
|
||||
uint8_t hdr[64] = {0};
|
||||
ssize_t n = :: pread(fd, hdr, sizeof(hdr), 0);
|
||||
if (n < 44 || std::memcmp(hdr, "RIFF", 4) != 0 ||
|
||||
std::memcmp(hdr + 8, "WAVE", 4) != 0) {
|
||||
::close(fd);
|
||||
return;
|
||||
}
|
||||
uint32_t riffLen = static_cast<uint32_t>(st.st_size - 8);
|
||||
uint32_t curRiff = static_cast<uint32_t>(hdr[4]) |
|
||||
(static_cast<uint32_t>(hdr[5]) << 8) |
|
||||
(static_cast<uint32_t>(hdr[6]) << 16) |
|
||||
(static_cast<uint32_t>(hdr[7]) << 24);
|
||||
if (curRiff == 0 || curRiff != riffLen) {
|
||||
uint8_t b[4] = {
|
||||
static_cast<uint8_t>(riffLen & 0xff),
|
||||
static_cast<uint8_t>((riffLen >> 8) & 0xff),
|
||||
static_cast<uint8_t>((riffLen >> 16) & 0xff),
|
||||
static_cast<uint8_t>((riffLen >> 24) & 0xff),
|
||||
};
|
||||
(void)::pwrite(fd, b, 4, 4);
|
||||
}
|
||||
for (ssize_t off = 12; off + 8 <= n;) {
|
||||
uint32_t chunkLen = static_cast<uint32_t>(hdr[off + 4]) |
|
||||
(static_cast<uint32_t>(hdr[off + 5]) << 8) |
|
||||
(static_cast<uint32_t>(hdr[off + 6]) << 16) |
|
||||
(static_cast<uint32_t>(hdr[off + 7]) << 24);
|
||||
if (std::memcmp(hdr + off, "data", 4) == 0) {
|
||||
uint32_t expectedData = static_cast<uint32_t>(st.st_size - (off + 8));
|
||||
if (chunkLen == 0 || chunkLen != expectedData) {
|
||||
uint8_t b[4] = {
|
||||
static_cast<uint8_t>(expectedData & 0xff),
|
||||
static_cast<uint8_t>((expectedData >> 8) & 0xff),
|
||||
static_cast<uint8_t>((expectedData >> 16) & 0xff),
|
||||
static_cast<uint8_t>((expectedData >> 24) & 0xff),
|
||||
};
|
||||
(void)::pwrite(fd, b, 4, off + 4);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (chunkLen == 0) break;
|
||||
off += 8 + static_cast<ssize_t>((chunkLen + 1) & ~1u);
|
||||
}
|
||||
::fsync(fd);
|
||||
::close(fd);
|
||||
}
|
||||
|
||||
void wakeDisplayHardware(Display* dpy) {
|
||||
int saved = readIntFile("/tmp/sxmo_saved_brightness", -1);
|
||||
if (saved <= 1) {
|
||||
@@ -365,7 +420,7 @@ int callscreen_run_main(int argc, char** argv) {
|
||||
reloadContactsIfNeeded();
|
||||
|
||||
AlsaCallControl alsa;
|
||||
unsigned int savedMicMux = 2;
|
||||
unsigned int savedMicMux = 1;
|
||||
|
||||
CallState callState = CallState::Idle;
|
||||
std::string callId;
|
||||
@@ -400,17 +455,17 @@ int callscreen_run_main(int argc, char** argv) {
|
||||
int64_t softkeyDeadlineMs = 0;
|
||||
|
||||
auto refreshHardwareAudioState = [&]() {
|
||||
unsigned int dec1 = alsa.getEnum("DEC1 MUX", 2);
|
||||
unsigned int dec1 = alsa.getEnum("DEC1 MUX", 1);
|
||||
if (dec1 > 0) {
|
||||
savedMicMux = dec1;
|
||||
writeIntFile("/tmp/xdrawer_mic_mux", static_cast<int>(savedMicMux));
|
||||
micMuted = false;
|
||||
} else {
|
||||
savedMicMux = static_cast<unsigned int>(std::max(1, readIntFile("/tmp/xdrawer_mic_mux", 2)));
|
||||
savedMicMux = static_cast<unsigned int>(std::max(1, readIntFile("/tmp/xdrawer_mic_mux", 1)));
|
||||
micMuted = true;
|
||||
}
|
||||
bool spkSwitch = alsa.getBoolean("SPK DAC Switch", false);
|
||||
bool earSwitch = alsa.getBoolean("EAR_S", true);
|
||||
bool earSwitch = (alsa.getEnum("EAR_S", 1) != 0);
|
||||
speakerOn = (spkSwitch && !earSwitch);
|
||||
|
||||
long rawVol = speakerOn ? alsa.getInteger("RX3 Digital Volume", 68)
|
||||
@@ -427,8 +482,9 @@ int callscreen_run_main(int argc, char** argv) {
|
||||
|
||||
auto setMicMuted = [&](bool mute) {
|
||||
micMuted = mute;
|
||||
alsa.setEnum("DEC1 MUX", mute ? 0 : savedMicMux);
|
||||
alsa.setInteger("ADC3 Volume", mute ? 0 : 8);
|
||||
alsa.setEnum("DEC1 MUX", mute ? 0 : (savedMicMux > 0 ? savedMicMux : 1));
|
||||
alsa.setInteger("ADC1 Volume", mute ? 0 : 6);
|
||||
alsa.setInteger("ADC3 Volume", mute ? 0 : 6);
|
||||
alsa.setBoolean("VoiceMMode1 Capture Mixer TERT_MI2S_TX", !mute);
|
||||
runAsyncCmd(mute ? "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ 1 >/dev/null 2>&1"
|
||||
: "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ 0 >/dev/null 2>&1");
|
||||
@@ -440,21 +496,19 @@ int callscreen_run_main(int argc, char** argv) {
|
||||
speakerOn = toSpeaker;
|
||||
long hwVol = std::lround((callVolumePct * 84.0) / 100.0);
|
||||
if (toSpeaker) {
|
||||
alsa.setBoolean("EAR_S", false);
|
||||
alsa.setEnum("EAR_S", 0);
|
||||
alsa.setEnum("RX1 MIX1 INP1", 0);
|
||||
alsa.setBoolean("SPK DAC Switch", true);
|
||||
alsa.setEnum("RX3 MIX1 INP1", 1);
|
||||
alsa.setEnum("RX3 MIX1 INP1", 3);
|
||||
alsa.setInteger("RX3 Digital Volume", hwVol);
|
||||
runAsyncCmd("sxmo_audio.sh device set Speaker >/dev/null 2>&1");
|
||||
statusNotice = "Audio routed to Speaker";
|
||||
} else {
|
||||
alsa.setBoolean("SPK DAC Switch", false);
|
||||
alsa.setEnum("RX3 MIX1 INP1", 0);
|
||||
alsa.setEnum("RX1 MIX1 INP1", 1);
|
||||
alsa.setEnum("RDAC2 MUX", 1);
|
||||
alsa.setBoolean("EAR_S", true);
|
||||
alsa.setEnum("RX1 MIX1 INP1", 3);
|
||||
alsa.setEnum("RDAC2 MUX", 0);
|
||||
alsa.setEnum("EAR_S", 1);
|
||||
alsa.setInteger("RX1 Digital Volume", hwVol);
|
||||
runAsyncCmd("sxmo_audio.sh device set Earpiece >/dev/null 2>&1");
|
||||
statusNotice = "Audio routed to Earpiece";
|
||||
}
|
||||
statusNoticeUntilMs = nowMs() + 2000;
|
||||
@@ -482,6 +536,7 @@ int callscreen_run_main(int argc, char** argv) {
|
||||
pid_t r = ::waitpid(recordPid, &status, WNOHANG);
|
||||
if (r == recordPid || (r < 0 && ::kill(recordPid, 0) != 0)) {
|
||||
recordPid = -1;
|
||||
finalizeWavHeader(recordFilePath);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -492,7 +547,7 @@ int callscreen_run_main(int argc, char** argv) {
|
||||
return;
|
||||
}
|
||||
::kill(recordPid, SIGINT);
|
||||
for (int i = 0; i < 15; ++i) {
|
||||
for (int i = 0; i < 150; ++i) {
|
||||
int status = 0;
|
||||
if (::waitpid(recordPid, &status, WNOHANG) == recordPid) {
|
||||
recordPid = -1;
|
||||
@@ -502,9 +557,15 @@ int callscreen_run_main(int argc, char** argv) {
|
||||
}
|
||||
if (recordPid > 0) {
|
||||
::kill(recordPid, SIGTERM);
|
||||
(void)::waitpid(recordPid, nullptr, WNOHANG);
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
if (::waitpid(recordPid, nullptr, WNOHANG) == recordPid) {
|
||||
break;
|
||||
}
|
||||
usleep(10000);
|
||||
}
|
||||
recordPid = -1;
|
||||
}
|
||||
finalizeWavHeader(recordFilePath);
|
||||
if (!recordFileName.empty()) {
|
||||
statusNotice = "Saved: " + recordFileName;
|
||||
statusNoticeUntilMs = nowMs() + 3500;
|
||||
@@ -527,7 +588,12 @@ int callscreen_run_main(int argc, char** argv) {
|
||||
recordFileName = "call_" + tag + "_" + tsBuf + ".wav";
|
||||
recordFilePath = dir + "/" + recordFileName;
|
||||
|
||||
// Ensure MultiMedia2 capture mixer is enabled for PipeWire recording
|
||||
// Ensure MultiMedia2 capture mixer and primary mic path are active for PipeWire recording
|
||||
alsa.setEnum("CIC1 MUX", 0);
|
||||
if (!micMuted) {
|
||||
alsa.setEnum("DEC1 MUX", savedMicMux > 0 ? savedMicMux : 1);
|
||||
alsa.setInteger("ADC1 Volume", 6);
|
||||
}
|
||||
alsa.setBoolean("MultiMedia2 Mixer TERT_MI2S_TX", true);
|
||||
|
||||
pid_t pid = ::fork();
|
||||
@@ -536,6 +602,12 @@ int callscreen_run_main(int argc, char** argv) {
|
||||
}
|
||||
if (pid == 0) {
|
||||
::setsid();
|
||||
std::string runtimeDir = "/run/user/" + std::to_string(::getuid());
|
||||
const char* xdg = std::getenv("XDG_RUNTIME_DIR");
|
||||
struct stat stRuntime {};
|
||||
if (!xdg || !*xdg || ::stat(xdg, &stRuntime) != 0) {
|
||||
::setenv("XDG_RUNTIME_DIR", runtimeDir.c_str(), 1);
|
||||
}
|
||||
int nullfd = ::open("/dev/null", O_RDWR);
|
||||
if (nullfd >= 0) {
|
||||
::dup2(nullfd, STDIN_FILENO);
|
||||
@@ -545,8 +617,9 @@ int callscreen_run_main(int argc, char** argv) {
|
||||
::close(nullfd);
|
||||
}
|
||||
}
|
||||
execlp("pw-record", "pw-record", "--rate", "16000", "--channels", "1",
|
||||
recordFilePath.c_str(), static_cast<char*>(nullptr));
|
||||
execlp("pw-record", "pw-record", "--format", "s16", "--rate", "16000",
|
||||
"--channels", "1", recordFilePath.c_str(),
|
||||
static_cast<char*>(nullptr));
|
||||
execlp("parecord", "parecord", "--rate=16000", "--channels=1",
|
||||
"--file-format=wav", recordFilePath.c_str(), static_cast<char*>(nullptr));
|
||||
execlp("arecord", "arecord", "-f", "S16_LE", "-r", "16000", "-c", "1",
|
||||
@@ -1055,6 +1128,12 @@ int callscreen_run_main(int argc, char** argv) {
|
||||
if (micMuted) {
|
||||
setMicMuted(false);
|
||||
}
|
||||
alsa.setBoolean("PRI_MI2S_RX Voice Mixer VoiceMMode1", false);
|
||||
alsa.setBoolean("VoiceMMode1 Capture Mixer TERT_MI2S_TX", false);
|
||||
alsa.setEnum("EAR_S", 0);
|
||||
alsa.setEnum("RX3 MIX1 INP1", 3);
|
||||
alsa.setBoolean("SPK DAC Switch", true);
|
||||
runAsyncCmd("sxmo_modemaudio.sh disable_call_audio_mode >/dev/null 2>&1");
|
||||
if (callStartMs > 0 &&
|
||||
(callState == CallState::Active || callState == CallState::Outgoing)) {
|
||||
lastFinalDurationSec = static_cast<int>((nowMs() - callStartMs) / 1000);
|
||||
|
||||
@@ -275,6 +275,7 @@ void applySystemSpeakerVol(int pct) {
|
||||
int rx3 = (pct <= 0) ? 0 : (54 + (pct * 38) / 100);
|
||||
runAsyncCmd("amixer -c 0 cset \"name='SPK DAC Switch'\" " +
|
||||
std::string(pct > 0 ? "1" : "0") + " >/dev/null 2>&1; "
|
||||
"amixer -c 0 cset \"name='RX3 MIX1 INP1'\" 3 >/dev/null 2>&1; "
|
||||
"amixer -c 0 cset \"name='RX3 Digital Volume'\" " +
|
||||
std::to_string(rx3) + " >/dev/null 2>&1; "
|
||||
"wpctl set-mute @DEFAULT_AUDIO_SINK@ " +
|
||||
@@ -433,7 +434,12 @@ int runMusicApp(int argc, char** argv) {
|
||||
ipcReadBuf.clear();
|
||||
if (mpvPid > 0) {
|
||||
::kill(mpvPid, SIGTERM);
|
||||
::waitpid(mpvPid, nullptr, WNOHANG);
|
||||
for (int i = 0; i < 15; ++i) {
|
||||
if (::waitpid(mpvPid, nullptr, WNOHANG) == mpvPid) {
|
||||
break;
|
||||
}
|
||||
usleep(10000);
|
||||
}
|
||||
mpvPid = -1;
|
||||
}
|
||||
::unlink(kMpvSockPath);
|
||||
@@ -456,6 +462,12 @@ int runMusicApp(int argc, char** argv) {
|
||||
pid_t pid = ::fork();
|
||||
if (pid == 0) {
|
||||
::setsid();
|
||||
std::string runtimeDir = "/run/user/" + std::to_string(::getuid());
|
||||
const char* xdg = std::getenv("XDG_RUNTIME_DIR");
|
||||
struct stat stRuntime {};
|
||||
if (!xdg || !*xdg || ::stat(xdg, &stRuntime) != 0) {
|
||||
::setenv("XDG_RUNTIME_DIR", runtimeDir.c_str(), 1);
|
||||
}
|
||||
int devNull = ::open("/dev/null", O_RDWR);
|
||||
if (devNull >= 0) {
|
||||
::dup2(devNull, STDIN_FILENO);
|
||||
@@ -466,8 +478,9 @@ int runMusicApp(int argc, char** argv) {
|
||||
std::string ipcArg =
|
||||
std::string("--input-ipc-server=") + kMpvSockPath;
|
||||
::execlp("mpv", "mpv", "--no-video", "--no-terminal", "--quiet",
|
||||
"--idle=yes", "--keep-open=no", "--volume-max=150",
|
||||
"--volume=100", ipcArg.c_str(),
|
||||
"--ao=pipewire,pulse,alsa", "--audio-channels=stereo",
|
||||
"--audio-samplerate=48000", "--idle=yes", "--keep-open=no",
|
||||
"--volume-max=150", "--volume=100", ipcArg.c_str(),
|
||||
static_cast<char*>(nullptr));
|
||||
::_exit(127);
|
||||
} else if (pid > 0) {
|
||||
@@ -519,7 +532,9 @@ int runMusicApp(int argc, char** argv) {
|
||||
isPaused = false;
|
||||
ignoreEofUntilMs = nowMs() + 450;
|
||||
|
||||
runAsyncCmd("amixer -c 0 cset \"name='SPK DAC Switch'\" 1 >/dev/null 2>&1; "
|
||||
runAsyncCmd("amixer -c 0 cset \"name='EAR_S'\" 0 >/dev/null 2>&1; "
|
||||
"amixer -c 0 cset \"name='SPK DAC Switch'\" 1 >/dev/null 2>&1; "
|
||||
"amixer -c 0 cset \"name='RX3 MIX1 INP1'\" 3 >/dev/null 2>&1; "
|
||||
"wpctl set-mute @DEFAULT_AUDIO_SINK@ 0 >/dev/null 2>&1");
|
||||
|
||||
ensureMpvRunning();
|
||||
|
||||
@@ -70,7 +70,13 @@ bool isAudioExtension(const std::string& name, std::string* extUpperOut = nullpt
|
||||
if (dot == std::string::npos || dot + 1 >= name.size()) return false;
|
||||
std::string ext = toLowerStr(name.substr(dot + 1));
|
||||
if (ext == "wav" || ext == "ogg" || ext == "mp3" ||
|
||||
ext == "flac" || ext == "opus" || ext == "m4a") {
|
||||
ext == "flac" || ext == "opus" || ext == "m4a" ||
|
||||
ext == "aac" || ext == "wma" || ext == "aiff" || ext == "aif" ||
|
||||
ext == "mod" || ext == "xm" || ext == "it" || ext == "s3m" ||
|
||||
ext == "mptm" || ext == "stm" || ext == "med" || ext == "okt" ||
|
||||
ext == "669" || ext == "ult" || ext == "far" || ext == "mtm" ||
|
||||
ext == "ptm" || ext == "amf" || ext == "dsm" || ext == "imf" ||
|
||||
ext == "gdm" || ext == "stx" || ext == "umx" || ext == "mo3") {
|
||||
if (extUpperOut) {
|
||||
*extUpperOut = ext;
|
||||
for (char& c : *extUpperOut) {
|
||||
@@ -139,6 +145,7 @@ std::vector<RingtoneEntry> discoverRingtones() {
|
||||
scanDirectoryForRingtones(home + "/Ringtones", "User", list);
|
||||
scanDirectoryForRingtones(home + "/Music/Ringtones", "User", list);
|
||||
scanDirectoryForRingtones(home + "/Music", "Music", list);
|
||||
scanDirectoryForRingtones("/usr/share/sxmo/music", "Tracker", list);
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -381,13 +388,21 @@ int runRingtonesApp(int argc, char** argv) {
|
||||
int rx3 = (rvol <= 0) ? 0 : (60 + rvol * 34 / 100);
|
||||
int mpvVol = rvol * 130 / 100;
|
||||
std::string volArg = "--volume=" + std::to_string(mpvVol);
|
||||
runAsyncCmd("amixer -c 0 cset \"name='SPK DAC Switch'\" 1 >/dev/null 2>&1; "
|
||||
runAsyncCmd("amixer -c 0 cset \"name='EAR_S'\" 0 >/dev/null 2>&1; "
|
||||
"amixer -c 0 cset \"name='SPK DAC Switch'\" 1 >/dev/null 2>&1; "
|
||||
"amixer -c 0 cset \"name='RX3 MIX1 INP1'\" 3 >/dev/null 2>&1; "
|
||||
"amixer -c 0 cset \"name='RX3 Digital Volume'\" " +
|
||||
std::to_string(rx3) + " >/dev/null 2>&1; "
|
||||
"wpctl set-mute @DEFAULT_AUDIO_SINK@ 0 >/dev/null 2>&1; "
|
||||
"wpctl set-volume @DEFAULT_AUDIO_SINK@ 100% >/dev/null 2>&1");
|
||||
pid_t pid = ::fork();
|
||||
if (pid == 0) {
|
||||
std::string runtimeDir = "/run/user/" + std::to_string(::getuid());
|
||||
const char* xdg = std::getenv("XDG_RUNTIME_DIR");
|
||||
struct stat stRuntime {};
|
||||
if (!xdg || !*xdg || ::stat(xdg, &stRuntime) != 0) {
|
||||
::setenv("XDG_RUNTIME_DIR", runtimeDir.c_str(), 1);
|
||||
}
|
||||
int devNull = ::open("/dev/null", O_RDWR);
|
||||
if (devNull >= 0) {
|
||||
::dup2(devNull, STDIN_FILENO);
|
||||
@@ -396,7 +411,9 @@ int runRingtonesApp(int argc, char** argv) {
|
||||
if (devNull > 2) ::close(devNull);
|
||||
}
|
||||
::execlp("mpv", "mpv", "--no-resume-playback", "--quiet",
|
||||
"--no-video", "--volume-max=150", volArg.c_str(),
|
||||
"--no-video", "--ao=pipewire,pulse,alsa",
|
||||
"--audio-channels=stereo", "--audio-samplerate=48000",
|
||||
"--volume-max=150", volArg.c_str(),
|
||||
"--loop=2", path.c_str(), nullptr);
|
||||
::_exit(127);
|
||||
} else if (pid > 0) {
|
||||
|
||||
@@ -333,12 +333,12 @@ class PhoneController {
|
||||
"Sound", false, 0, 1, 1, spkOn ? 1 : 0});
|
||||
|
||||
// 7. Microphone on/off (toggle)
|
||||
unsigned int dec1 = alsa_.getEnum("DEC1 MUX", 2);
|
||||
unsigned int dec1 = alsa_.getEnum("DEC1 MUX", 1);
|
||||
if (dec1 > 0) {
|
||||
savedMicMux_ = dec1;
|
||||
writeIntFile("/tmp/xdrawer_mic_mux", static_cast<int>(savedMicMux_));
|
||||
} else {
|
||||
savedMicMux_ = static_cast<unsigned int>(std::max(1, readIntFile("/tmp/xdrawer_mic_mux", 2)));
|
||||
savedMicMux_ = static_cast<unsigned int>(std::max(1, readIntFile("/tmp/xdrawer_mic_mux", 1)));
|
||||
}
|
||||
items_.push_back({ControlId::MicMute, kIconMicOn, kIconMicOff,
|
||||
"Microphone", false, 0, 1, 1, (dec1 > 0) ? 1 : 0});
|
||||
@@ -470,6 +470,7 @@ class PhoneController {
|
||||
long hw = (it.value <= 0) ? 0 : (60 + std::lround((it.value * 32.0) / 100.0));
|
||||
if (it.value > 0) {
|
||||
alsa_.setBoolean("SPK DAC Switch", true);
|
||||
alsa_.setEnum("RX3 MIX1 INP1", 3);
|
||||
}
|
||||
alsa_.setInteger("RX3 Digital Volume", hw);
|
||||
char cmd[160];
|
||||
@@ -501,6 +502,9 @@ class PhoneController {
|
||||
}
|
||||
case ControlId::SoundMute: {
|
||||
alsa_.setBoolean("SPK DAC Switch", it.value != 0);
|
||||
if (it.value != 0) {
|
||||
alsa_.setEnum("RX3 MIX1 INP1", 3);
|
||||
}
|
||||
runAsyncCmd(it.value
|
||||
? "wpctl set-mute @DEFAULT_AUDIO_SINK@ 0 >/dev/null 2>&1; "
|
||||
"sxmo_hook_statusbar.sh audio >/dev/null 2>&1"
|
||||
@@ -509,8 +513,9 @@ class PhoneController {
|
||||
break;
|
||||
}
|
||||
case ControlId::MicMute: {
|
||||
alsa_.setEnum("DEC1 MUX", it.value ? savedMicMux_ : 0);
|
||||
alsa_.setInteger("ADC3 Volume", it.value ? 8 : 0);
|
||||
alsa_.setEnum("DEC1 MUX", it.value ? (savedMicMux_ > 0 ? savedMicMux_ : 1) : 0);
|
||||
alsa_.setInteger("ADC1 Volume", it.value ? 6 : 0);
|
||||
alsa_.setInteger("ADC3 Volume", it.value ? 6 : 0);
|
||||
runAsyncCmd(it.value
|
||||
? "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ 0 >/dev/null 2>&1"
|
||||
: "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ 1 >/dev/null 2>&1");
|
||||
|
||||
Reference in New Issue
Block a user