Stream auf BubbleUPnP starten

Begonnen von nesges, 29 Januar 2015, 13:14:27

Vorheriges Thema - Nächstes Thema

nesges

Mit den folgenden Funktionen starte ich einen Stream auf einem Android-Gerät mit BubbleUPnP. Das funktioniert soweit, hat aber einen großen Nachteil: Es ist langsam (Dauer bis zum Start des Streams zwischen 5 und 15 Sekunden) und blockiert in der Zeit. Da ich's bisher nur zum Ansteuern eines "Weckers" benutze, ist das für mich in Ordnung. Für TTS o.ä. wäre der Code in der vorliegenden Form aber ungeeignet.

Folgende Perl-Module müssen verfügbar sein:

use LWP::Simple;
use Net::UPnP::ControlPoint;
use Net::UPnP::AV::MediaRenderer;


Der Code gehört zB in die 99_myUtils.pm. Weitere Erläuterungen in den Kommentaren.

# Starte die Wiedergabe einer M3U-Playlist auf UPnP Geräten
#
# upnp_playlist_m3u(<m3u_uri> [, <upnp_searchstring>])
#
#   m3u_uri:            URI zu einem Playlist-File im M3U-Format
#   upnp_searchstring:  UPnP-Suchstring, default: upnp:rootdevice
#
#   Parameter zwei ist optional. Wird er weggelassen, wird versucht die
#   Wiedergabe auf ALLEN gefundenen UPnP-Mediarenderern zu starten.
#
# Beispiel:
#
#   upnp_playlist_m3u('http://www.deutschlandradio.de/streaming/dlf.m3u', 'uuid:cfcdcf5a-b44a-c055-ffff-ffffb5da2133')
#
#   Lädt das Playlist-File des Deutschlandfunks und versucht die darin
#   notierten Streams auf dem UPnP-Gerät mit der UUID cfcdcf5a-b44a-c055-ffff-ffffb5da2133
#   wieder zu geben.
#
sub upnp_playlist_m3u($;$) {
    my $uri = shift;
    my $usearch = shift;
   
    Log 4, "upnp_playlist_m3u: fetching ".$uri;
    my $doc = get($uri);
    my @streams = split /[\r\n]+/, $doc;

    upnp_play(\@streams, $usearch);
}

# Stoppe die Wiedergabe auf UPnP Geräten
#
# upnp_stop([<upnp_searchstring>])
#
#   upnp_searchstring:  siehe upnp_playlist_m3u()
#
sub upnp_stop(;$) {
    my $usearch = shift || 'upnp:rootdevice';
    upnp_play(0, $usearch);
}

# Starte die Wiedergabe eines Streams auf UPnP Geräten
#
# upnp_stop([<stream_uri>] [,<upnp_searchstring>])
#
#   stream_uri:         URI eines Medienstreams
#   upnp_searchstring:  siehe upnp_playlist_m3u()
#
sub upnp_play(;$$) {
    my $media = shift || 0;
    my $usearch = shift || 'upnp:rootdevice';

    my $obj = Net::UPnP::ControlPoint->new();

    my @dev_list = ();
    my $retry_cnt = 0;
    while (@dev_list <= 0 && $retry_cnt < 5) {
        Log 4, "upnp_play: searching UPnP devices with: $usearch (tries: ".$retry_cnt++.")";
        @dev_list = $obj->search(st => $usearch, mx => 3);
    }
   
    foreach my $dev (@dev_list) {
        my $device_type = $dev->getdevicetype();
        if  ($device_type ne 'urn:schemas-upnp-org:device:MediaRenderer:1') {
            next;
        }
        my $uuid = $dev->getudn();
        my $friendlyname = $dev->getfriendlyname();
        Log 4, "upnp_play: found UPnP device: $friendlyname / $uuid";
       
        eval {
            my $renderer = Net::UPnP::AV::MediaRenderer->new();
            $renderer->setdevice($dev);
            $renderer->stop();
       
            if($media) {
                my $response;
                my $response_code;
                my $m = 0;
                do {
               
                    $response = $renderer->setAVTransportURI(CurrentURI => $media->[$m]);
                    $response_code = $response->getstatuscode();
                    if($response_code==200) {
                        $response = $renderer->play();
                        $response_code = $response->getstatuscode();
                    }
                    Log 4, "upnp_play: ".$response_code." ".$media->[$m];
                    $m++;
                } until($response_code==200 || $m > $#{ $media })
            }
        } || do {
            Log 1, "upnp_play: Error on $friendlyname / $uuid: ".join ' ', $@;
        }
    }
}

# Listet alle in Frage kommenden UPnP Geräten is Log
#
# upnp_list()
#
# Dem Log kann der UPnP-Searchstring für die anderen upnp-Funktionen
# entnommen werden. Beispiel:
#
# 2015.01.29 12:48:33 1: found UPnP device: BubbleUPnP (SPX-5_3G) / uuid:1b3c3bca-3a57-9044-ffff-ffff8c2ef2d7
#
# "uuid:1b3c3bca-3a57-9044-ffff-ffff8c2ef2d7" ist der gesuchte Searchstring,
# der zB in upnp_stop("uuid:1b3c3bca-3a57-9044-ffff-ffff8c2ef2d7")
# verwendet werden kann.
#
# Auf Loglevel 3 wird eine weitere Zeile mit der XML-Beschreibung des
# UPnP-Gerätes ausgegeben.
#
sub upnp_list() {
    my $obj = Net::UPnP::ControlPoint->new();

    my @dev_list = ();
    my $retry_cnt = 0;
    while (@dev_list <= 0 && $retry_cnt < 5) {
        @dev_list = $obj->search(st => 'upnp:rootdevice', mx => 3);
    }
   
    foreach my $dev (@dev_list) {
        my $device_type = $dev->getdevicetype();
        if  ($device_type ne 'urn:schemas-upnp-org:device:MediaRenderer:1') {
            next;
        }
        my $uuid = $dev->getudn();
        my $friendlyname = $dev->getfriendlyname();
        Log 1, "found UPnP device: $friendlyname / $uuid";
        Log 3, $dev->getdescription();
    }
}