Debug DeleteId de openhome
This commit is contained in:
@@ -1696,18 +1696,34 @@ impl ControlPoint {
|
||||
auto_play: bool,
|
||||
) -> anyhow::Result<()> {
|
||||
// CRITICAL: When attaching a new playlist to a renderer, we must UNCONDITIONALLY
|
||||
// clear the queue first. This is different from refreshing an already-attached
|
||||
// playlist (which uses gentle sync to avoid interrupting playback).
|
||||
// clear the RENDERER queue first (but NOT the local queue cache, which will be
|
||||
// replaced by refresh_attached_queue_for() using replace_entire_playlist()).
|
||||
//
|
||||
// Attach workflow: Stop (if playing) → Clear → Fill → Play
|
||||
// Attach workflow: Clear renderer → Fill with new playlist
|
||||
// Update workflow: Gentle sync (preserve current item, use LCS)
|
||||
info!(
|
||||
renderer = renderer_id.0.as_str(),
|
||||
server = server_id.0.as_str(),
|
||||
container = container_id,
|
||||
"Attaching new playlist: clearing queue first"
|
||||
"Attaching new playlist: clearing renderer queue"
|
||||
);
|
||||
self.clear_queue(renderer_id)?;
|
||||
|
||||
// Clear the renderer's queue for OpenHome renderers
|
||||
// We also sync the local cache to reflect the empty state, which will trigger
|
||||
// refresh_attached_queue_for() to use replace_entire_playlist() instead of gentle sync
|
||||
if self.runtime.uses_openhome_playlist(renderer_id) {
|
||||
let renderer = self.openhome_renderer(renderer_id)?;
|
||||
renderer.openhome_playlist_clear()?;
|
||||
// Sync local cache to reflect the empty renderer state
|
||||
self.sync_openhome_playlist_for(renderer_id)?;
|
||||
debug!(
|
||||
renderer = renderer_id.0.as_str(),
|
||||
"Cleared OpenHome renderer playlist and synced local cache"
|
||||
);
|
||||
} else {
|
||||
// For non-OpenHome renderers, use the standard clear_queue
|
||||
self.clear_queue(renderer_id)?;
|
||||
}
|
||||
|
||||
let binding = PlaylistBinding {
|
||||
server_id: server_id.clone(),
|
||||
@@ -2622,6 +2638,9 @@ fn refresh_attached_queue_for(
|
||||
let current_item = current_idx.and_then(|idx| full_queue.get(idx).cloned());
|
||||
|
||||
// Check if renderer is playing - if so, we MUST preserve the current track
|
||||
// We use multiple signals to determine playback state:
|
||||
// 1. Direct playback_state() query (may fail on some renderers like upmpdcli)
|
||||
// 2. Presence of current_idx (if we have a current track, likely playing)
|
||||
let is_playing = {
|
||||
let renderer_info = {
|
||||
let reg = registry.read().unwrap();
|
||||
@@ -2630,7 +2649,20 @@ fn refresh_attached_queue_for(
|
||||
|
||||
if let Some(info) = renderer_info {
|
||||
if let Some(renderer) = MusicRenderer::from_registry_info(info, registry) {
|
||||
matches!(renderer.playback_state(), Ok(PlaybackState::Playing))
|
||||
// Try direct query first
|
||||
if matches!(renderer.playback_state(), Ok(PlaybackState::Playing)) {
|
||||
true
|
||||
} else if current_idx.is_some() && !full_queue.is_empty() {
|
||||
// Fallback: if we have a current index and non-empty queue,
|
||||
// assume playback is happening (handles renderers where playback_state() fails)
|
||||
debug!(
|
||||
renderer = renderer_id.0.as_str(),
|
||||
"playback_state() failed or not Playing, but current_idx is set - assuming playback"
|
||||
);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
@@ -121,12 +121,12 @@ impl OhPlaylistClient {
|
||||
|
||||
pub fn play_id(&self, id: u32) -> Result<()> {
|
||||
let id_str = id.to_string();
|
||||
let args = [("Id", id_str.as_str())];
|
||||
let args = [("Value", id_str.as_str())];
|
||||
|
||||
let call_result =
|
||||
invoke_upnp_action(&self.control_url, &self.service_type, "PlayId", &args)?;
|
||||
invoke_upnp_action(&self.control_url, &self.service_type, "SeekId", &args)?;
|
||||
|
||||
handle_action_response("PlayId", &call_result)
|
||||
handle_action_response("SeekId", &call_result)
|
||||
}
|
||||
|
||||
pub fn play(&self) -> Result<()> {
|
||||
@@ -170,7 +170,7 @@ impl OhPlaylistClient {
|
||||
|
||||
pub fn delete_id(&self, id: u32) -> Result<()> {
|
||||
let id_str = id.to_string();
|
||||
let args = [("Id", id_str.as_str())];
|
||||
let args = [("Value", id_str.as_str())];
|
||||
|
||||
let call_result =
|
||||
invoke_upnp_action(&self.control_url, &self.service_type, "DeleteId", &args)?;
|
||||
@@ -221,6 +221,16 @@ impl OhPlaylistClient {
|
||||
handle_action_response("DeleteAll", &call_result)
|
||||
}
|
||||
|
||||
pub fn current_id(&self) -> Result<String> {
|
||||
let call_result =
|
||||
invoke_upnp_action(&self.control_url, &self.service_type, "Id", &[])?;
|
||||
let envelope = ensure_success("Id", &call_result)?;
|
||||
let response = find_child_with_suffix(&envelope.body.content, "IdResponse")
|
||||
.ok_or_else(|| anyhow!("Missing IdResponse element in SOAP body"))?;
|
||||
let value: String = extract_child_text_any(response, &["aValue", "Value"])?;
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn tracks_max(&self) -> Result<u32> {
|
||||
let call_result =
|
||||
invoke_upnp_action(&self.control_url, &self.service_type, "TracksMax", &[])?;
|
||||
@@ -228,7 +238,7 @@ impl OhPlaylistClient {
|
||||
let envelope = ensure_success("TracksMax", &call_result)?;
|
||||
let response = find_child_with_suffix(&envelope.body.content, "TracksMaxResponse")
|
||||
.ok_or_else(|| anyhow!("Missing TracksMaxResponse element in SOAP body"))?;
|
||||
let value_text = extract_child_text_any(response, &["aValue", "Value"])?;
|
||||
let value_text: String = extract_child_text_any(response, &["aValue", "Value"])?;
|
||||
let value = value_text
|
||||
.parse::<u32>()
|
||||
.map_err(|_| anyhow!("Invalid TracksMax value: {}", value_text))?;
|
||||
|
||||
Reference in New Issue
Block a user