All pastes #986207 Raw Edit

sonos_upnp_update

public text v1 · immutable
·published 2008-04-15 17:00 UTC
rendered paste body
sub 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 =~ /&lt/) {
            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);
        }
    }
}