Usage of Coherence (or GUPnP)? to stream A/V?

2.5k views Asked by At

After looking for some time to a solution for streaming audio/video via uPnP, Coherence seems to be the most promising option: For example: http://coherence.beebits.net/browser/trunk/Coherence/coherence/backends/gstreamer_renderer.py seems to be what would be required to play a file directly to a HDMI TV dongle.

Oddly enough, after installing the Ubuntu coherence package, running import coherence in Python terminal doesn't really show anything like this module. Tab completion in bpython shows:

>>> coherence.
┌───────────────────────────────────────────────────────────────────────────┐
│SERVER_ID           Version             platform                           │
│sys                 twisted_version     twisted_web_version                │
└───────────────────────────────────────────────────────────────────────────┘

and those submodules seem to just give info about the system. How do I import and use Coherence to stream the desktop, or a video, to a uPnP screen? Is there a basic getting started guide?

Update

It looks like GUPnP has ability to link in to Python:

>>> from gi.repository import GUPnP
>>> GUPnP.ControlPoint.new()
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: new() takes exactly 2 arguments (0 given)

Which is apparently calling the function documented here: https://developer.gnome.org/gupnp/unstable/GUPnPControlPoint.html

Unfortunately the docs don't have any full examples of how to stream to a video receiver - specifically, how does it initiate sending the video file over the network?

Update: This is the first step I use to detect the device:

import socket
import threading
import time

Addr = None;
StartLock = threading.Lock()

def DoUDP():
    global Addr
    global StartLock
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #Internet, UDP
    s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    while 1:
        s.sendto('0:0',('192.168.0.255',63630))
        data,addr = s.recvfrom(1024)
        print data
        print 'from', addr
        Addr = addr
        try:
            StartLock.release()
        except:
            pass
        time.sleep(1)
        return

StartLock.acquire()
print 'starting...'
udpthread = threading.Thread(target=DoUDP)
udpthread.start();

#... knowing address of the device... send stuff?
1

There are 1 answers

3
Jussi Kukkonen On

About GUPnP on python: it's not extensively used and definitely not documented well enough but it should work. Here's a quick example of listing the available devices on wlan0 network using a GUPnP ControlPoint:

from gi.repository import GLib, GUPnP

def device_available (cp, proxy):
   print ("Found " + proxy.get_friendly_name ())

ctx = GUPnP.Context.new (None, "wlan0", 0)
cp = GUPnP.ControlPoint.new (ctx, "upnp:rootdevice")
cp.set_active (True)
cp.connect ("device-proxy-available", device_available)

GLib.MainLoop ().run ()

The problem with "streaming to a renderer" is that you actually need two things: the control point that tells the renderer what you want to play, and the mediaserver that serves the actual media when the renderer asks for it -- if these are integrated into one (called the "2-box push model"), the mediaserver part is not quite as complex but it still needs to be done.

One project you may be interested in is dleyna: It is based on GUPnP and tries to make this client side work a little easier. See Jens' article and documentation for PushHost. However dleyna is a set of D-Bus services, not a library so you'll have to decide if it fits your purposes.

Alternatively you can of course have a normal mediaserver (like rygel) running and use a control point (like gupnp-av-cp from gupnp-tools) to select the media you want to play and the renderer that should play it.