Fix piano playback controls and recorded settings
This commit is contained in:
@@ -87,7 +87,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"keys": "Piano mode",
|
"keys": "Piano mode",
|
||||||
"description": "When using a piano: 1-9 (and 0 for the 10th slot) changes instrument, -/= changes octave, ASDFGHJKL;' plays C major notes, WETYUOP] plays sharps, comma starts/stops recording, period plays recording, Escape exits"
|
"description": "When using a piano: 1-9 (and 0 for the 10th slot) changes instrument, -/= changes octave, ASDFGHJKL;' plays C major notes, WETYUOP] plays sharps, comma starts/stops recording, period plays recording, slash stops playback, Escape exits"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Maintainer-controlled web client version.
|
// Maintainer-controlled web client version.
|
||||||
// Format: YYYY.MM.DD Rn (example: 2026.02.20 R2)
|
// Format: YYYY.MM.DD Rn (example: 2026.02.20 R2)
|
||||||
window.CHGRID_WEB_VERSION = "2026.02.22 R205";
|
window.CHGRID_WEB_VERSION = "2026.02.22 R206";
|
||||||
// Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid.
|
// Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid.
|
||||||
window.CHGRID_TIME_ZONE = "America/Detroit";
|
window.CHGRID_TIME_ZONE = "America/Detroit";
|
||||||
|
|||||||
@@ -995,7 +995,7 @@ function handlePianoUseModeKeyUp(code: string): void {
|
|||||||
/** Plays one short C4 preview using the piano item's current/overridden envelope+instrument. */
|
/** Plays one short C4 preview using the piano item's current/overridden envelope+instrument. */
|
||||||
async function previewPianoSettingChange(
|
async function previewPianoSettingChange(
|
||||||
item: WorldItem,
|
item: WorldItem,
|
||||||
overrides: Partial<{ instrument: PianoInstrumentId; attack: number; decay: number; release: number; brightness: number }>,
|
overrides: Partial<{ instrument: PianoInstrumentId; octave: number; attack: number; decay: number; release: number; brightness: number }>,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (item.type !== 'piano') return;
|
if (item.type !== 'piano') return;
|
||||||
await audio.ensureContext();
|
await audio.ensureContext();
|
||||||
@@ -1004,6 +1004,7 @@ async function previewPianoSettingChange(
|
|||||||
if (!ctx || !destination) return;
|
if (!ctx || !destination) return;
|
||||||
const current = getPianoParams(item);
|
const current = getPianoParams(item);
|
||||||
const instrument = overrides.instrument ?? current.instrument;
|
const instrument = overrides.instrument ?? current.instrument;
|
||||||
|
const octave = Math.max(-2, Math.min(2, Math.round(overrides.octave ?? current.octave)));
|
||||||
const attack = Math.max(0, Math.min(100, Math.round(overrides.attack ?? current.attack)));
|
const attack = Math.max(0, Math.min(100, Math.round(overrides.attack ?? current.attack)));
|
||||||
const decay = Math.max(0, Math.min(100, Math.round(overrides.decay ?? current.decay)));
|
const decay = Math.max(0, Math.min(100, Math.round(overrides.decay ?? current.decay)));
|
||||||
const release = Math.max(0, Math.min(100, Math.round(overrides.release ?? current.release)));
|
const release = Math.max(0, Math.min(100, Math.round(overrides.release ?? current.release)));
|
||||||
@@ -1015,7 +1016,7 @@ async function previewPianoSettingChange(
|
|||||||
pianoSynth.noteOn(
|
pianoSynth.noteOn(
|
||||||
previewKeyId,
|
previewKeyId,
|
||||||
'preview',
|
'preview',
|
||||||
60,
|
Math.max(0, Math.min(127, 60 + octave * 12)),
|
||||||
instrument,
|
instrument,
|
||||||
'poly',
|
'poly',
|
||||||
attack,
|
attack,
|
||||||
@@ -2423,12 +2424,17 @@ function handlePianoUseModeInput(code: string): void {
|
|||||||
audio.sfxUiBlip();
|
audio.sfxUiBlip();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (code === 'Slash') {
|
||||||
|
signaling.send({ type: 'item_piano_recording', itemId, action: 'stop_playback' });
|
||||||
|
audio.sfxUiBlip();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (code === 'Equal' || code === 'Minus') {
|
if (code === 'Equal' || code === 'Minus') {
|
||||||
const current = getPianoParams(item).octave;
|
const current = getPianoParams(item).octave;
|
||||||
const next = Math.max(-2, Math.min(2, current + (code === 'Equal' ? 1 : -1)));
|
const next = Math.max(-2, Math.min(2, current + (code === 'Equal' ? 1 : -1)));
|
||||||
item.params.octave = next;
|
item.params.octave = next;
|
||||||
signaling.send({ type: 'item_update', itemId, params: { octave: next } });
|
signaling.send({ type: 'item_update', itemId, params: { octave: next } });
|
||||||
void previewPianoSettingChange(item, {});
|
void previewPianoSettingChange(item, { octave: next });
|
||||||
updateStatus(`octave ${next}.`);
|
updateStatus(`octave ${next}.`);
|
||||||
if (next === current) {
|
if (next === current) {
|
||||||
audio.sfxUiCancel();
|
audio.sfxUiCancel();
|
||||||
@@ -2462,6 +2468,7 @@ function handlePianoUseModeInput(code: string): void {
|
|||||||
});
|
});
|
||||||
void previewPianoSettingChange(item, {
|
void previewPianoSettingChange(item, {
|
||||||
instrument,
|
instrument,
|
||||||
|
octave,
|
||||||
attack: defaults.attack,
|
attack: defaults.attack,
|
||||||
decay: defaults.decay,
|
decay: defaults.decay,
|
||||||
release: defaults.release,
|
release: defaults.release,
|
||||||
@@ -2749,8 +2756,10 @@ const itemPropertyEditor = createItemPropertyEditor({
|
|||||||
if (key === 'instrument') {
|
if (key === 'instrument') {
|
||||||
const instrument = normalizePianoInstrument(value);
|
const instrument = normalizePianoInstrument(value);
|
||||||
const defaults = DEFAULT_PIANO_SETTINGS_BY_INSTRUMENT[instrument];
|
const defaults = DEFAULT_PIANO_SETTINGS_BY_INSTRUMENT[instrument];
|
||||||
|
const octave = defaultsOctaveForInstrument(instrument);
|
||||||
void previewPianoSettingChange(item, {
|
void previewPianoSettingChange(item, {
|
||||||
instrument,
|
instrument,
|
||||||
|
octave,
|
||||||
attack: defaults.attack,
|
attack: defaults.attack,
|
||||||
decay: defaults.decay,
|
decay: defaults.decay,
|
||||||
release: defaults.release,
|
release: defaults.release,
|
||||||
@@ -2783,7 +2792,9 @@ const itemPropertyEditor = createItemPropertyEditor({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (key === 'octave') {
|
if (key === 'octave') {
|
||||||
void previewPianoSettingChange(item, {});
|
const octave = Number(value);
|
||||||
|
if (!Number.isFinite(octave)) return;
|
||||||
|
void previewPianoSettingChange(item, { octave });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
updateStatus,
|
updateStatus,
|
||||||
|
|||||||
@@ -243,6 +243,13 @@ export function createOnMessageHandler(deps: MessageHandlerDeps): (message: Inco
|
|||||||
case 'item_action_result': {
|
case 'item_action_result': {
|
||||||
if (message.ok) {
|
if (message.ok) {
|
||||||
if (message.action === 'use') {
|
if (message.action === 'use') {
|
||||||
|
const pianoStatusLabel =
|
||||||
|
message.message === 'record' || message.message === 'play' || message.message === 'stop' ? message.message : null;
|
||||||
|
if (pianoStatusLabel) {
|
||||||
|
deps.updateStatus(pianoStatusLabel);
|
||||||
|
deps.audioUiBlip();
|
||||||
|
break;
|
||||||
|
}
|
||||||
deps.pushChatMessage(message.message);
|
deps.pushChatMessage(message.message);
|
||||||
const item = message.itemId ? deps.getItemById(message.itemId) : null;
|
const item = message.itemId ? deps.getItemById(message.itemId) : null;
|
||||||
if (!item?.useSound && item && item.type !== 'piano') {
|
if (!item?.useSound && item && item.type !== 'piano') {
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ export type OutgoingMessage =
|
|||||||
| { type: 'item_delete'; itemId: string }
|
| { type: 'item_delete'; itemId: string }
|
||||||
| { type: 'item_use'; itemId: string }
|
| { type: 'item_use'; itemId: string }
|
||||||
| { type: 'item_piano_note'; itemId: string; keyId: string; midi: number; on: boolean }
|
| { type: 'item_piano_note'; itemId: string; keyId: string; midi: number; on: boolean }
|
||||||
| { type: 'item_piano_recording'; itemId: string; action: 'toggle_record' | 'playback' }
|
| { type: 'item_piano_recording'; itemId: string; action: 'toggle_record' | 'playback' | 'stop_playback' }
|
||||||
| {
|
| {
|
||||||
type: 'item_update';
|
type: 'item_update';
|
||||||
itemId: string;
|
itemId: string;
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ Applies to effect select, user/item list modes, item selection, item property li
|
|||||||
- `-` / `=`: Shift octave down/up
|
- `-` / `=`: Shift octave down/up
|
||||||
- `,`: Start/stop recording on this piano (max 30s)
|
- `,`: Start/stop recording on this piano (max 30s)
|
||||||
- `.`: Play back saved recording on this piano
|
- `.`: Play back saved recording on this piano
|
||||||
|
- `/`: Stop playback on this piano
|
||||||
- `Escape`: Exit piano mode
|
- `Escape`: Exit piano mode
|
||||||
|
|
||||||
## Help Viewer Mode
|
## Help Viewer Mode
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ This is a behavior guide for packet semantics beyond raw schemas.
|
|||||||
- `ping`: latency measurement.
|
- `ping`: latency measurement.
|
||||||
- `item_add`, `item_pickup`, `item_drop`, `item_delete`, `item_use`, `item_update`: item actions.
|
- `item_add`, `item_pickup`, `item_drop`, `item_delete`, `item_use`, `item_update`: item actions.
|
||||||
- `item_piano_note`: realtime piano note on/off for active piano use mode.
|
- `item_piano_note`: realtime piano note on/off for active piano use mode.
|
||||||
- `item_piano_recording`: piano record/playback control (`toggle_record`, `playback`).
|
- `item_piano_recording`: piano record/playback control (`toggle_record`, `playback`, `stop_playback`).
|
||||||
|
|
||||||
## Server -> Client
|
## Server -> Client
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ class ItemPianoNotePacket(BasePacket):
|
|||||||
class ItemPianoRecordingPacket(BasePacket):
|
class ItemPianoRecordingPacket(BasePacket):
|
||||||
type: Literal["item_piano_recording"]
|
type: Literal["item_piano_recording"]
|
||||||
itemId: str
|
itemId: str
|
||||||
action: Literal["toggle_record", "playback"]
|
action: Literal["toggle_record", "playback", "stop_playback"]
|
||||||
|
|
||||||
|
|
||||||
class ItemUpdatePacket(BasePacket):
|
class ItemUpdatePacket(BasePacket):
|
||||||
|
|||||||
@@ -195,20 +195,57 @@ class SignalingServer:
|
|||||||
key_id: str,
|
key_id: str,
|
||||||
midi: int,
|
midi: int,
|
||||||
on: bool,
|
on: bool,
|
||||||
|
instrument_override: str | None = None,
|
||||||
|
voice_mode_override: str | None = None,
|
||||||
|
attack_override: int | None = None,
|
||||||
|
decay_override: int | None = None,
|
||||||
|
release_override: int | None = None,
|
||||||
|
brightness_override: int | None = None,
|
||||||
|
emit_range_override: int | None = None,
|
||||||
exclude: ServerConnection | None = None,
|
exclude: ServerConnection | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Broadcast one piano note event using current item synth settings."""
|
"""Broadcast one piano note event using current item synth settings."""
|
||||||
|
|
||||||
instrument = str(item.params.get("instrument", "piano")).strip().lower()
|
instrument = (instrument_override if isinstance(instrument_override, str) else str(item.params.get("instrument", "piano"))).strip().lower()
|
||||||
voice_mode = str(item.params.get("voiceMode", "poly")).strip().lower()
|
voice_mode = (voice_mode_override if isinstance(voice_mode_override, str) else str(item.params.get("voiceMode", "poly"))).strip().lower()
|
||||||
if voice_mode not in {"poly", "mono"}:
|
if voice_mode not in {"poly", "mono"}:
|
||||||
voice_mode = "poly"
|
voice_mode = "poly"
|
||||||
octave = int(item.params.get("octave", 0)) if isinstance(item.params.get("octave", 0), (int, float)) else 0
|
octave = int(item.params.get("octave", 0)) if isinstance(item.params.get("octave", 0), (int, float)) else 0
|
||||||
attack = int(item.params.get("attack", 15)) if isinstance(item.params.get("attack", 15), (int, float)) else 15
|
attack = (
|
||||||
decay = int(item.params.get("decay", 45)) if isinstance(item.params.get("decay", 45), (int, float)) else 45
|
int(attack_override)
|
||||||
release = int(item.params.get("release", 35)) if isinstance(item.params.get("release", 35), (int, float)) else 35
|
if isinstance(attack_override, int)
|
||||||
brightness = int(item.params.get("brightness", 55)) if isinstance(item.params.get("brightness", 55), (int, float)) else 55
|
else int(item.params.get("attack", 15))
|
||||||
emit_range = int(item.params.get("emitRange", 15)) if isinstance(item.params.get("emitRange", 15), (int, float)) else 15
|
if isinstance(item.params.get("attack", 15), (int, float))
|
||||||
|
else 15
|
||||||
|
)
|
||||||
|
decay = (
|
||||||
|
int(decay_override)
|
||||||
|
if isinstance(decay_override, int)
|
||||||
|
else int(item.params.get("decay", 45))
|
||||||
|
if isinstance(item.params.get("decay", 45), (int, float))
|
||||||
|
else 45
|
||||||
|
)
|
||||||
|
release = (
|
||||||
|
int(release_override)
|
||||||
|
if isinstance(release_override, int)
|
||||||
|
else int(item.params.get("release", 35))
|
||||||
|
if isinstance(item.params.get("release", 35), (int, float))
|
||||||
|
else 35
|
||||||
|
)
|
||||||
|
brightness = (
|
||||||
|
int(brightness_override)
|
||||||
|
if isinstance(brightness_override, int)
|
||||||
|
else int(item.params.get("brightness", 55))
|
||||||
|
if isinstance(item.params.get("brightness", 55), (int, float))
|
||||||
|
else 55
|
||||||
|
)
|
||||||
|
emit_range = (
|
||||||
|
int(emit_range_override)
|
||||||
|
if isinstance(emit_range_override, int)
|
||||||
|
else int(item.params.get("emitRange", 15))
|
||||||
|
if isinstance(item.params.get("emitRange", 15), (int, float))
|
||||||
|
else 15
|
||||||
|
)
|
||||||
source_x, source_y = self._get_piano_source_position(item)
|
source_x, source_y = self._get_piano_source_position(item)
|
||||||
await self._broadcast(
|
await self._broadcast(
|
||||||
ItemPianoNoteBroadcastPacket(
|
ItemPianoNoteBroadcastPacket(
|
||||||
@@ -273,7 +310,7 @@ class SignalingServer:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
await asyncio.sleep(PIANO_RECORDING_MAX_MS / 1000)
|
await asyncio.sleep(PIANO_RECORDING_MAX_MS / 1000)
|
||||||
await self._finalize_piano_recording(item_id, status_message="Recording reached 30.0 s and was saved.")
|
await self._finalize_piano_recording(item_id, status_message="stop")
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -294,12 +331,26 @@ class SignalingServer:
|
|||||||
raw_on = event.get("on")
|
raw_on = event.get("on")
|
||||||
if not isinstance(raw_time, (int, float)) or not isinstance(raw_key, str) or not isinstance(raw_midi, (int, float)) or not isinstance(raw_on, bool):
|
if not isinstance(raw_time, (int, float)) or not isinstance(raw_key, str) or not isinstance(raw_midi, (int, float)) or not isinstance(raw_on, bool):
|
||||||
continue
|
continue
|
||||||
|
raw_instrument = event.get("instrument")
|
||||||
|
raw_voice_mode = event.get("voiceMode")
|
||||||
|
raw_attack = event.get("attack")
|
||||||
|
raw_decay = event.get("decay")
|
||||||
|
raw_release = event.get("release")
|
||||||
|
raw_brightness = event.get("brightness")
|
||||||
|
raw_emit_range = event.get("emitRange")
|
||||||
events.append(
|
events.append(
|
||||||
{
|
{
|
||||||
"t": max(0, min(PIANO_RECORDING_MAX_MS, int(raw_time))),
|
"t": max(0, min(PIANO_RECORDING_MAX_MS, int(raw_time))),
|
||||||
"keyId": raw_key[:32] or "KeyA",
|
"keyId": raw_key[:32] or "KeyA",
|
||||||
"midi": max(0, min(127, int(raw_midi))),
|
"midi": max(0, min(127, int(raw_midi))),
|
||||||
"on": raw_on,
|
"on": raw_on,
|
||||||
|
"instrument": str(raw_instrument).strip().lower() if isinstance(raw_instrument, str) else None,
|
||||||
|
"voiceMode": str(raw_voice_mode).strip().lower() if isinstance(raw_voice_mode, str) else None,
|
||||||
|
"attack": max(0, min(100, int(raw_attack))) if isinstance(raw_attack, (int, float)) else None,
|
||||||
|
"decay": max(0, min(100, int(raw_decay))) if isinstance(raw_decay, (int, float)) else None,
|
||||||
|
"release": max(0, min(100, int(raw_release))) if isinstance(raw_release, (int, float)) else None,
|
||||||
|
"brightness": max(0, min(100, int(raw_brightness))) if isinstance(raw_brightness, (int, float)) else None,
|
||||||
|
"emitRange": max(5, min(20, int(raw_emit_range))) if isinstance(raw_emit_range, (int, float)) else None,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
events.sort(key=lambda entry: int(entry["t"]))
|
events.sort(key=lambda entry: int(entry["t"]))
|
||||||
@@ -330,6 +381,13 @@ class SignalingServer:
|
|||||||
key_id=key_id,
|
key_id=key_id,
|
||||||
midi=midi,
|
midi=midi,
|
||||||
on=on,
|
on=on,
|
||||||
|
instrument_override=event.get("instrument") if isinstance(event.get("instrument"), str) else None,
|
||||||
|
voice_mode_override=event.get("voiceMode") if isinstance(event.get("voiceMode"), str) else None,
|
||||||
|
attack_override=event.get("attack") if isinstance(event.get("attack"), int) else None,
|
||||||
|
decay_override=event.get("decay") if isinstance(event.get("decay"), int) else None,
|
||||||
|
release_override=event.get("release") if isinstance(event.get("release"), int) else None,
|
||||||
|
brightness_override=event.get("brightness") if isinstance(event.get("brightness"), int) else None,
|
||||||
|
emit_range_override=event.get("emitRange") if isinstance(event.get("emitRange"), int) else None,
|
||||||
)
|
)
|
||||||
previous_at_ms = current_at_ms
|
previous_at_ms = current_at_ms
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
@@ -877,9 +935,32 @@ class SignalingServer:
|
|||||||
elapsed_ms = max(0, min(PIANO_RECORDING_MAX_MS, int((time.monotonic() - started) * 1000)))
|
elapsed_ms = max(0, min(PIANO_RECORDING_MAX_MS, int((time.monotonic() - started) * 1000)))
|
||||||
events = recording_state.get("events")
|
events = recording_state.get("events")
|
||||||
if isinstance(events, list) and len(events) < PIANO_RECORDING_MAX_EVENTS:
|
if isinstance(events, list) and len(events) < PIANO_RECORDING_MAX_EVENTS:
|
||||||
events.append({"t": elapsed_ms, "keyId": packet.keyId[:32], "midi": packet.midi, "on": packet.on})
|
instrument = str(item.params.get("instrument", "piano")).strip().lower()
|
||||||
|
voice_mode = str(item.params.get("voiceMode", "poly")).strip().lower()
|
||||||
|
if voice_mode not in {"poly", "mono"}:
|
||||||
|
voice_mode = "poly"
|
||||||
|
attack = int(item.params.get("attack", 15)) if isinstance(item.params.get("attack", 15), (int, float)) else 15
|
||||||
|
decay = int(item.params.get("decay", 45)) if isinstance(item.params.get("decay", 45), (int, float)) else 45
|
||||||
|
release = int(item.params.get("release", 35)) if isinstance(item.params.get("release", 35), (int, float)) else 35
|
||||||
|
brightness = int(item.params.get("brightness", 55)) if isinstance(item.params.get("brightness", 55), (int, float)) else 55
|
||||||
|
emit_range = int(item.params.get("emitRange", 15)) if isinstance(item.params.get("emitRange", 15), (int, float)) else 15
|
||||||
|
events.append(
|
||||||
|
{
|
||||||
|
"t": elapsed_ms,
|
||||||
|
"keyId": packet.keyId[:32],
|
||||||
|
"midi": packet.midi,
|
||||||
|
"on": packet.on,
|
||||||
|
"instrument": instrument,
|
||||||
|
"voiceMode": voice_mode,
|
||||||
|
"attack": max(0, min(100, attack)),
|
||||||
|
"decay": max(0, min(100, decay)),
|
||||||
|
"release": max(0, min(100, release)),
|
||||||
|
"brightness": max(0, min(100, brightness)),
|
||||||
|
"emitRange": max(5, min(20, emit_range)),
|
||||||
|
}
|
||||||
|
)
|
||||||
if elapsed_ms >= PIANO_RECORDING_MAX_MS:
|
if elapsed_ms >= PIANO_RECORDING_MAX_MS:
|
||||||
await self._finalize_piano_recording(item.id, status_message="Recording reached 30.0 s and was saved.")
|
await self._finalize_piano_recording(item.id, status_message="stop")
|
||||||
await self._broadcast_item_piano_note(
|
await self._broadcast_item_piano_note(
|
||||||
item,
|
item,
|
||||||
sender_id=client.id,
|
sender_id=client.id,
|
||||||
@@ -908,7 +989,7 @@ class SignalingServer:
|
|||||||
await self._send_item_result(client, False, "use", "This piano is already recording.", item.id)
|
await self._send_item_result(client, False, "use", "This piano is already recording.", item.id)
|
||||||
return
|
return
|
||||||
if existing and existing.get("ownerClientId") == client.id:
|
if existing and existing.get("ownerClientId") == client.id:
|
||||||
await self._finalize_piano_recording(item.id, status_message="Recording saved.")
|
await self._finalize_piano_recording(item.id, status_message="stop")
|
||||||
return
|
return
|
||||||
self._cancel_piano_playback(item.id)
|
self._cancel_piano_playback(item.id)
|
||||||
recording_state = {
|
recording_state = {
|
||||||
@@ -919,7 +1000,7 @@ class SignalingServer:
|
|||||||
self.piano_recording_state_by_item[item.id] = recording_state
|
self.piano_recording_state_by_item[item.id] = recording_state
|
||||||
auto_stop_task = asyncio.create_task(self._auto_stop_piano_recording(item.id))
|
auto_stop_task = asyncio.create_task(self._auto_stop_piano_recording(item.id))
|
||||||
recording_state["autoStopTask"] = auto_stop_task
|
recording_state["autoStopTask"] = auto_stop_task
|
||||||
await self._send_item_result(client, True, "use", "Recording started. Press comma again to stop.", item.id)
|
await self._send_item_result(client, True, "use", "record", item.id)
|
||||||
return
|
return
|
||||||
|
|
||||||
if packet.action == "playback":
|
if packet.action == "playback":
|
||||||
@@ -933,7 +1014,12 @@ class SignalingServer:
|
|||||||
self._cancel_piano_playback(item.id)
|
self._cancel_piano_playback(item.id)
|
||||||
playback_task = asyncio.create_task(self._start_piano_playback(item))
|
playback_task = asyncio.create_task(self._start_piano_playback(item))
|
||||||
self.piano_playback_tasks_by_item[item.id] = playback_task
|
self.piano_playback_tasks_by_item[item.id] = playback_task
|
||||||
await self._send_item_result(client, True, "use", f"Playing recording on {item.title}.", item.id)
|
await self._send_item_result(client, True, "use", "play", item.id)
|
||||||
|
return
|
||||||
|
|
||||||
|
if packet.action == "stop_playback":
|
||||||
|
self._cancel_piano_playback(item.id)
|
||||||
|
await self._send_item_result(client, True, "use", "stop", item.id)
|
||||||
return
|
return
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user