Warning: session_start(): open(/var/lib/php/sessions/sess_uatbfptd0g27a3sq8p129qhmvb, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
!7
srecord AudioSource(S description, S volume, S baseVolume, bool mute, int index) {}
module ListAudioSources > DynObjectTable {
//transient SimpleLiveValue lvVolume = floatLiveValue(); // for selected source
transient JTextField tfVolume;
start {
set fieldsInOrder;
dontPersist();
doEveryAndNow(10.0, r updateList);
}
void updateList enter {
LS lines = lines(backtick("pactl list sources"));
new Matches m;
new L list;
for i over lines:
if (swic(lines.get(i), "Source #")) {
int idx = parseFirstInt(lines.get(i));
AudioSource as = nu(AudioSource, index := idx, description := lines.get(i));
for (int j = i+1; j < l(lines); j++) {
S line = lines.get(j);
if (!startsWithSpace(line)) break;
line = trim(line);
if (swic_trim(line, "Description:", m))
as.description = m.rest();
else if (swic_trim(line, "Base Volume:", m))
as.baseVolume = m.rest();
else if (swic_trim(line, "Volume:", m))
as.volume = iround(parseFirstInt(m.rest())*100.0/65536) + "%";
else if (swic_trim(line, "Mute:", m))
as.mute = isYes(m.rest());
}
list.add(as);
}
setData(list);
}
visualize {
JComponent c = super.visualize();
onTableSelectionChanged(table, r {
setText(tfVolume, selected() == null ? "" : firstIntAsString(selected().volume))
});
tfVolume = jTextField();
onEnter(tfVolume, r {
if (selected() == null) ret;
backtickToConsole("pactl set-source-volume " + selected().index + " " + iround(parseFirstInt(gtt(tfVolume))/100.0*65536));
updateList();
});
ret centerAndEastWithMargins(c, vstackWithSpacing(
tableDependentButton_extraCondition(table, "Mute",
rThread {
muteSource(selected())
}, func -> bool { !selected().mute }),
tableDependentButton_extraCondition(table, "Unmute",
rThread {
unmuteSource(selected())
}, func -> bool { selected().mute }),
jlabel("Volume:"),
tfVolume
,
jbutton("Export", r { showText("Audio source settings", exportAsText()) })
));
}
// API
S getSourceName(int index) {
ret getString(objectWhere(data, +index), 'description);
}
AudioSource findSourceByName(S name) {
ret objectWhereIC(data, description := name);
}
void muteSource(AudioSource src) {
if (src == null) ret;
backtickToConsole("pactl set-source-mute " + src.index + " 1");
updateList();
}
void unmuteSource(AudioSource src) {
if (src == null) ret;
backtickToConsole("pactl set-source-mute " + src.index + " 0");
updateList();
}
bool isSourceMuted(AudioSource src) {
ret src != null && src.mute;
}
S exportAsText() {
ret linesMap(data(), func(AudioSource src) -> S {
(src.mute ? "Muted audio source" : "Audio source")
+ quote(src.description) + " has volume " + parseFirstInt(src.volume) + "."
});
}
}