rendered paste bodysub sonos_upnp_update {
my ($service, %properties) = @_;
Log (2, "Event received for service=" . $service->{BASE} . " id = " . $service->serviceId);
# Log(4, Dumper(\%properties));
# Save off the zone names
if ($service->serviceId =~ /serviceId:ZoneGroupTopology/) {
foreach my $key (keys %properties) {
if ($key eq "ZoneGroupState") {
my $tree = XMLin(decode_entities($properties{$key}),
forcearray => ["ZoneGroup", "ZoneGroupMember"]);
Log(4, "ZoneGroupTopology " . Dumper($tree));
foreach my $group (@{$tree->{ZoneGroup}}) {
my %zonegroup = %{$group};
foreach my $member (@{$zonegroup{ZoneGroupMember}}) {
my $zkey = $member->{UUID};
foreach my $mkey (keys %{$member}) {
$main::ZONES{$zkey}->{$mkey} = $member->{$mkey};
}
$main::ZONES{$zkey}->{Coordinator} = $zonegroup{Coordinator};
my @ip = split(/\//, $member->{Location});
$main::ZONES{$zkey}->{IPPORT} = $ip[2];
$main::ZONES{$zkey}->{AV}->{LASTUPDATE} = 1 if (!defined $main::ZONES{$zkey}->{AV}->{LASTUPDATE});
$main::ZONES{$zkey}->{RENDER}->{LASTUPDATE} = 1 if (!defined $main::ZONES{$zkey}->{RENDER}->{LASTUPDATE});
$main::ZONES{$zkey}->{AV}->{CurrentTrackMetaData} = "" if (!defined $main::ZONES{$zkey}->{AV}->{CurrentTrackMetaData});
$main::QUEUEUPDATE{$zkey} = 1 if (!defined $main::QUEUEUPDATE{$zkey});
}
}
$main::LASTUPDATE = $main::SONOS_UPDATENUM;
$main::ZONESUPDATE = $main::SONOS_UPDATENUM++;
sonos_process_waiting("ZONES");
} elsif ($key eq "ThirdPartyMediaServers") {
my $tree = XMLin(decode_entities($properties{$key}), forcearray => ["Service"]);
for my $item ( @{ $tree->{Service} } ) {
if($item->{UDN} =~ "SA_RINCON1_") { #Rhapsody
Log(2, "Adding Rhapsody Subscription");
$main::SERVICES{Rhapsody} = $item;
} elsif($item->{UDN} =~ "SA_RINCON4_") { #PANDORA
Log(2, "Adding Pandora Subscription");
$main::SERVICES{Pandora} = $item;
} elsif($item->{UDN} =~ "SA_RINCON6_") { #SIRIUS
Log(2, "Adding Sirius Subscription");
$main::SERVICES{Sirius} = $item;
}
}
sonos_process_waiting("SERVICES");
} else {
Log(4, "$key " . Dumper($properties{$key}));
}
}
}
my $zone = sonos_location_to_id($service->{BASE});
# Save off the current status
if ($service->serviceId =~ /serviceId:RenderingControl/) {
if (decode_entities($properties{LastChange}) eq "") {
Log(3, "Unknown RenderingControl " . Dumper(\%properties));
return;
}
my $tree = XMLin(decode_entities($properties{LastChange}),
forcearray => ["ZoneGroup"],
keyattr=>{"Volume" => "channel",
"Mute" => "channel",
"Loudness" => "channel"});
Log(4, "RenderingControl " . Dumper($tree));
foreach my $key ("Volume", "Treble", "Bass", "Mute", "Loudness") {
if ($tree->{InstanceID}->{$key}) {
$main::ZONES{$zone}->{RENDER}->{$key} = $tree->{InstanceID}->{$key};
$main::LASTUPDATE = $main::SONOS_UPDATENUM;
$main::ZONES{$zone}->{RENDER}->{LASTUPDATE} = $main::SONOS_UPDATENUM++;
}
}
sonos_process_waiting("RENDER", $zone);
return;
}
if ($service->serviceId =~ /serviceId:AVTransport/) {
if (decode_entities($properties{LastChange}) eq "") {
Log(3, "Unknown AVTransport " . Dumper(\%properties));
return;
}
my $tree = XMLin(decode_entities($properties{LastChange}));
Log(4, "AVTransport " . Dumper($tree));
foreach my $key ("CurrentTrackMetaData", "CurrentPlayMode", "NumberOfTracks", "CurrentTrack", "TransportState", "AVTransportURIMetaData", "AVTransportURI", "r:NextTrackMetaData", "CurrentTrackDuration") {
if ($tree->{InstanceID}->{$key}) {
$main::LASTUPDATE = $main::SONOS_UPDATENUM;
$main::ZONES{$zone}->{AV}->{LASTUPDATE} = $main::SONOS_UPDATENUM++;
if ($tree->{InstanceID}->{$key}->{val} =~ /^</) {
$tree->{InstanceID}->{$key}->{val} = decode_entities($tree->{InstanceID}->{$key}->{val});
}
if ($tree->{InstanceID}->{$key}->{val} =~ /^</) {
$main::ZONES{$zone}->{AV}->{$key} = \%{XMLin($tree->{InstanceID}->{$key}->{val})};
} else {
$main::ZONES{$zone}->{AV}->{$key} = $tree->{InstanceID}->{$key}->{val};
}
}
}
sonos_process_waiting("AV", $zone);
return;
}
if ($service->serviceId =~ /serviceId:ContentDirectory/) {
Log(4, "ContentDirectory " . Dumper(\%properties));
if (defined $properties{ContainerUpdateIDs} && $properties{ContainerUpdateIDs} =~ /AI:/) {
sonos_containers_del("AI:");
}
if (!defined $main::ZONES{$zone}->{QUEUE} || $properties{ContainerUpdateIDs} =~ /Q:0/) {
Log (2, "Refetching Q for $main::ZONES{$zone}->{ZoneName} updateid $properties{ContainerUpdateIDs}");
$main::ZONES{$zone}->{QUEUE} = upnp_content_dir_browse($zone, "Q:0");
$main::LASTUPDATE = $main::SONOS_UPDATENUM;
$main::QUEUEUPDATE{$zone} = $main::SONOS_UPDATENUM++;
sonos_process_waiting("QUEUE", $zone);
}
if (defined $properties{ShareIndexInProgress}) {
$main::UPDATEID{ShareIndexInProgress} = $properties{ShareIndexInProgress};
}
if (defined $properties{MasterRadioUpdateID} && ($properties{MasterRadioUpdateID} ne $main::UPDATEID{MasterRadioUpdateID})) {
$main::UPDATEID{MasterRadioUpdateID} = $properties{MasterRadioUpdateID};
sonos_containers_del("R:");
}
if (defined $properties{SavedQueuesUpdateID} && $properties{SavedQueuesUpdateID} ne $main::UPDATEID{SavedQueuesUpdateID}) {
$main::UPDATEID{SavedQueuesUpdateID} = $properties{SavedQueuesUpdateID};
sonos_containers_del("SQ:");
}
if (defined $properties{ShareListUpdateID} && $properties{ShareListUpdateID} ne $main::UPDATEID{ShareListUpdateID}) {
$main::UPDATEID{ShareListUpdateID} = $properties{ShareListUpdateID};
Log (2, "Refetching Index, update id $properties{ShareListUpdateID}");
add_timeout (time(), \&sonos_fetch_music);
}
return;
}
while (my ($key, $val) = each %properties) {
if ($val =~ /</) {
my $d = decode_entities($val);
my $tree = XMLin($d, forcearray => ["ZoneGroup"], keyattr=>{"ZoneGroup" => "ID"});
Log(3, "Property ${key}'s value is " . Dumper($tree));
} else {
Log(3, "Property ${key}'s value is " . $val);
}
}
}